// SPDX-License-Identifier: GPL-2.0 /* * Copyright (c) 2019 MediaTek Inc. */ #ifdef DFT_TAG #undef DFT_TAG #endif #define DFT_TAG "MTK-BTIF-EXP" /*#include "mtk_btif_exp.h"*/ #include "mtk_btif.h" /*---------------------------------Function----------------------------------*/ struct _mtk_btif_ *btif_exp_srh_id(unsigned long u_id) { int index = 0; struct _mtk_btif_ *p_btif = NULL; struct list_head *p_list = NULL; struct list_head *tmp = NULL; struct _mtk_btif_user_ *p_user = NULL; for (index = 0; (index < BTIF_PORT_NR) && (p_btif == NULL); index++) { p_list = &(g_btif[index].user_list); list_for_each(tmp, p_list) { p_user = container_of(tmp, struct _mtk_btif_user_, entry); if (u_id == p_user->u_id) { p_btif = p_user->p_btif; BTIF_DBG_FUNC ("BTIF's user id(%lu), p_btif(0x%p)\n", p_user->u_id, p_btif); break; } } } if (p_btif == NULL) { BTIF_INFO_FUNC ("no btif structure found for BTIF's user id(0x%lx)\n", u_id); } return p_btif; } /*-----Normal Mode API declearation-------*/ /***************************************************************************** * FUNCTION * mtk_wcn_btif_open * DESCRIPTION * open BTIF interface, will do BTIF module HW and SW initialization * PARAMETERS * p_owner [IN] pointer to owner who call this API, * currently there are 2 owner ("stp" or "btif_tester") * may use this module * for "stp", BTIF will call rx callback function to route rx data to STP * for "stp_tester", BTIF will save rx data and wait for native process * to access * p_id [IN] BTIF's user id will be put to this address * RETURNS * int 0 = BTIF module initialization fail; * negative = BTIF module initialization success * if open success, value p_id will be the only identifier * for user to access BTIF's other operations * including read/write/dpidle_ctrl/rx_cb_retister * this user id is only an identifier used for owner identification *****************************************************************************/ int mtk_wcn_btif_open(char *p_owner, unsigned long *p_id) { int i_ret = -1; unsigned int index = 0; struct _mtk_btif_user_ *p_new_user = NULL; struct _mtk_btif_ *p_btif = &g_btif[index]; struct list_head *p_user_list = &(p_btif->user_list); BTIF_DBG_FUNC("++"); BTIF_DBG_FUNC("p_btif(0x%p)\n", p_btif); if (mutex_lock_killable(&(p_btif->ops_mtx))) { BTIF_ERR_FUNC("mutex_lock_killable return failed\n"); return E_BTIF_INTR; } if ((p_owner == NULL) || (p_id == NULL)) { if (p_id) *p_id = 0; BTIF_ERR_FUNC("parameter invalid, p_owner(0x%p), p_id(0x%p)\n", p_owner, p_id); BTIF_MUTEX_UNLOCK(&(p_btif->ops_mtx)); return E_BTIF_INVAL_PARAM; } /*check if btif is already opened or not, if yes, just return fail*/ if (!list_empty(p_user_list)) { struct list_head *pos = NULL; struct _mtk_btif_user_ *p_user = NULL; BTIF_ERR_FUNC("BTIF's user list is not empty\n"); list_for_each(pos, p_user_list) { p_user = container_of(pos, struct _mtk_btif_user_, entry); BTIF_INFO_FUNC("BTIF's user id(0x%lx), name(%s)\n", p_user->u_id, p_user->u_name); } /*leave p_id alone*/ BTIF_MUTEX_UNLOCK(&(p_btif->ops_mtx)); return E_BTIF_ALREADY_OPEN; } p_new_user = vmalloc(sizeof(struct _mtk_btif_user_)); if (p_new_user != NULL) { INIT_LIST_HEAD(&(p_new_user->entry)); p_new_user->enable = false; p_new_user->p_btif = p_btif; p_new_user->u_id = (unsigned long)p_new_user; strncpy(p_new_user->u_name, p_owner, sizeof(p_new_user->u_name) - 1); p_new_user->u_name[sizeof(p_new_user->u_name) - 1] = '\0'; BTIF_DBG_FUNC("owner name:%s, recorded name:%s\n", p_owner, p_new_user->u_name); i_ret = btif_open(p_btif); if (i_ret) { BTIF_ERR_FUNC("btif_open failed, i_ret(%d)\n", i_ret); *p_id = 0; /*free btif new user's structure*/ vfree(p_new_user); p_new_user = NULL; } else { BTIF_INFO_FUNC("btif_open succeed\n"); *p_id = p_new_user->u_id; /*mark enable flag to true*/ p_new_user->enable = true; /*add to uer lsit*/ list_add_tail(&(p_new_user->entry), p_user_list); } } else { *p_id = 0; i_ret = -ENOMEM; BTIF_ERR_FUNC("alloc memory struct _mtk_btif_user_ failed\n"); } BTIF_MUTEX_UNLOCK(&(p_btif->ops_mtx)); BTIF_DBG_FUNC("--"); return i_ret; } EXPORT_SYMBOL(mtk_wcn_btif_open); /***************************************************************************** * FUNCTION * mtk_wcn_btif_close * DESCRIPTION * close BTIF interface, will do BTIF module HW and SW de-initialization * once this API is called, p_btif should never be used by BTIF's user again * PARAMETERS * u_id [IN] BTIF's user id * RETURNS * int 0 = succeed; * others = fail, * for detailed information, please see ENUM_BTIF_OP_ERROR_CODE *****************************************************************************/ int mtk_wcn_btif_close(unsigned long u_id) { int i_ret = -1; struct _mtk_btif_ *p_btif = NULL; struct list_head *pos = NULL; struct list_head *p_user_list = NULL; BTIF_DBG_FUNC("++"); p_btif = btif_exp_srh_id(u_id); if (p_btif == NULL) return E_BTIF_INVAL_PARAM; if (mutex_lock_killable(&(p_btif->ops_mtx))) { BTIF_ERR_FUNC("mutex_lock_killable return failed\n"); return E_BTIF_INTR; } p_user_list = &(p_btif->user_list); list_for_each(pos, p_user_list) { struct _mtk_btif_user_ *p_user = container_of(pos, struct _mtk_btif_user_, entry); if (p_user->u_id == u_id) { BTIF_INFO_FUNC ("user who's id is 0x%lx deleted from user list\n", u_id); list_del(pos); vfree(p_user); i_ret = btif_close(p_btif); if (i_ret) BTIF_WARN_FUNC("BTIF close failed"); break; } } BTIF_MUTEX_UNLOCK(&(p_btif->ops_mtx)); BTIF_DBG_FUNC("--"); return 0; } EXPORT_SYMBOL(mtk_wcn_btif_close); /***************************************************************************** * FUNCTION * mtk_wcn_btif_write * DESCRIPTION * send data throuth BTIF module * there's no internal buffer to cache STP data in BTIF driver, * if in DMA mode * btif driver will check if there's enough space in vFIFO for data to send * in DMA mode * if yes, put data to vFIFO and return corresponding data length to caller * if no, corresponding error code will be returned to called * PARAMETERS * p_btif [IN] pointer returned by mtk_wcn_btif_open * p_buf [IN] pointer to target data to send * len [IN] data length (less than 2014 bytes per STP package) * * if in non-DMA mode, BTIF driver will try to write to THR of BTIF controller * if btif driver detected that no space is available in Tx FIFO, * will return E_BTIF_NO_SPACE, mostly something is wrong with BTIF or * consys when this return value is returned * RETURNS * int positive: data length send through BTIF; * negative: please see ENUM_BTIF_OP_ERROR_CODE * E_BTIF_AGAIN (0) will be returned to caller * if btif does not have enough vFIFO to send data, * when caller get 0, he should wait for a moment * (5~10ms maybe) and try a few times (maybe 10~20) * if still get E_BTIF_AGAIN, * should call BTIF's debug API and dump BTIF driver * and BTIF/DMA register information to kernel log for debug * E_BTIF_BAD_POINTER will be returned to caller * if btif is not opened successfully before call this API * E_BTIF_INVAL_PARAM will be returned if parameter is not valid *****************************************************************************/ int mtk_wcn_btif_write(unsigned long u_id, const unsigned char *p_buf, unsigned int len) { int i_ret = -1; struct _mtk_btif_ *p_btif = NULL; BTIF_DBG_FUNC("++"); p_btif = btif_exp_srh_id(u_id); if (p_btif == NULL) return E_BTIF_INVAL_PARAM; if (p_buf == NULL) { BTIF_ERR_FUNC("invalid p_buf (0x%p)\n", p_buf); return E_BTIF_INVAL_PARAM; } if ((len == 0) || (len > BTIF_MAX_LEN_PER_PKT)) { BTIF_ERR_FUNC("invalid buffer length(%d)\n", len); return E_BTIF_INVAL_PARAM; } i_ret = btif_send_data(p_btif, p_buf, len); BTIF_DBG_FUNC("--, i_ret:%d\n", i_ret); return i_ret; } EXPORT_SYMBOL(mtk_wcn_btif_write); /***************************************************************************** * FUNCTION * mtk_wcn_btif_read * DESCRIPTION * read data from BTIF module * PARAMETERS * p_btif [IN] pointer returned by mtk_wcn_btif_open * p_buf [IN/OUT] pointer to buffer where rx data will be put * max_len [IN] max buffer length * RETURNS * int positive: data length read from BTIF; * negative: please see ENUM_BTIF_OP_ERROR_CODE *****************************************************************************/ int mtk_wcn_btif_read(unsigned long u_id, unsigned char *p_buf, unsigned int max_len) { return 0; } /***************************************************************************** * FUNCTION * mtk_wcn_btif_dpidle_ctrl * DESCRIPTION * control if BTIF module allow system enter deepidle state or not * PARAMETERS * p_btif [IN] pointer returned by mtk_wcn_btif_open * en_flag [IN] one of enum _ENUM_BTIF_DPIDLE_ * RETURNS * int always return 0 *****************************************************************************/ int mtk_wcn_btif_dpidle_ctrl(unsigned long u_id, enum _ENUM_BTIF_DPIDLE_ en_flag) { int i_ret = -1; struct _mtk_btif_ *p_btif = NULL; p_btif = btif_exp_srh_id(u_id); if (p_btif == NULL) return E_BTIF_INVAL_PARAM; if (en_flag == BTIF_DPIDLE_DISABLE) i_ret = btif_exit_dpidle(p_btif); else i_ret = btif_enter_dpidle(p_btif); return i_ret; } EXPORT_SYMBOL(mtk_wcn_btif_dpidle_ctrl); /***************************************************************************** * FUNCTION * mtk_wcn_btif_rx_cb_register * DESCRIPTION * register rx callback function to BTIF module by btif user * PARAMETERS * p_btif [IN] pointer returned by mtk_wcn_btif_open * rx_cb [IN] pointer to stp rx handler callback function, * should be comply with MTK_WCN_BTIF_RX_CB * RETURNS * int 0 = succeed; * others = fail, for detailed information, * please see ENUM_BTIF_OP_ERROR_CODE *****************************************************************************/ int mtk_wcn_btif_rx_cb_register(unsigned long u_id, MTK_WCN_BTIF_RX_CB rx_cb) { int i_ret = -1; struct _mtk_btif_ *p_btif = NULL; p_btif = btif_exp_srh_id(u_id); if (p_btif == NULL) return E_BTIF_INVAL_PARAM; i_ret = btif_rx_cb_reg(p_btif, rx_cb); return i_ret; } EXPORT_SYMBOL(mtk_wcn_btif_rx_cb_register); /***************************************************************************** * FUNCTION * mtk_wcn_btif_wakeup_consys * DESCRIPTION * once sleep command is sent to con sys, * should call this API before send wakeup command * to make con sys aware host want to send data to consys * PARAMETERS * p_btif [IN] pointer returned by mtk_wcn_btif_open * RETURNS * int 0 = succeed; others = fail, for detailed information, * please see ENUM_BTIF_OP_ERROR_CODE *****************************************************************************/ int mtk_wcn_btif_wakeup_consys(unsigned long u_id) { int i_ret = -1; struct _mtk_btif_ *p_btif = NULL; p_btif = btif_exp_srh_id(u_id); if (p_btif == NULL) return E_BTIF_INVAL_PARAM; /*i_ret = hal_btif_raise_wak_sig(p_btif->p_btif_info);*/ i_ret = btif_raise_wak_signal(p_btif); return i_ret; } EXPORT_SYMBOL(mtk_wcn_btif_wakeup_consys); /***************End of Normal Mode API declearation**********/ /***************Debug Purpose API declearation**********/ /***************************************************************************** * FUNCTION * mtk_wcn_btif_loopback_ctrl * DESCRIPTION * enable/disable BTIF internal loopback function, * when this function is enabled data send to btif * will be received by btif itself * only for debug purpose, should never use this function in normal mode * PARAMETERS * p_btif [IN] pointer returned by mtk_wcn_btif_open * enable [IN] loopback mode control flag, enable or disable, * shou be one of enum _ENUM_BTIF_LPBK_MODE_ * RETURNS * int 0 = succeed; * others = fail, for detailed information, please see ENUM_BTIF_OP_ERROR_CODE *****************************************************************************/ int mtk_wcn_btif_loopback_ctrl(unsigned long u_id, enum _ENUM_BTIF_LPBK_MODE_ enable) { int i_ret = -1; struct _mtk_btif_ *p_btif = NULL; p_btif = btif_exp_srh_id(u_id); if (p_btif == NULL) return E_BTIF_INVAL_PARAM; i_ret = btif_lpbk_ctrl(p_btif, enable == BTIF_LPBK_ENABLE ? true : false); return i_ret; } EXPORT_SYMBOL(mtk_wcn_btif_loopback_ctrl); /***************************************************************************** * FUNCTION * mtk_wcn_btif_logger_ctrl * DESCRIPTION * control BTIF logger function's behavior * PARAMETERS * p_btif [IN] pointer returned by mtk_wcn_btif_open * flag [IN] should be one of enum _ENUM_BTIF_DBG_ID_ * BTIF_DISABLE_LOGGER - disable btif logger * BTIF_ENABLE_LOGGER - enable btif logger * BTIF_DUMP_LOG - dump log logged by btif * BTIF_CLR_LOG - clear btif log buffer * BTIF_DUMP_BTIF_REG - dump btif controller's register * BTIF_DUMP_DMA_REG - dump DMA controller's register * RETURNS * int 0 = succeed; others = fail, for detailed information, * please see ENUM_BTIF_OP_ERROR_CODE *****************************************************************************/ int mtk_wcn_btif_dbg_ctrl(unsigned long u_id, enum _ENUM_BTIF_DBG_ID_ flag) { int i_ret = -1; struct _mtk_btif_ *p_btif = NULL; p_btif = btif_exp_srh_id(u_id); if (p_btif == NULL) return E_BTIF_INVAL_PARAM; i_ret = 0; switch (flag) { case BTIF_DISABLE_LOGGER:{ BTIF_INFO_FUNC ("disable btif log function for both Tx and Rx\n"); btif_log_buf_disable(&p_btif->tx_log); btif_log_buf_disable(&p_btif->rx_log); } break; case BTIF_ENABLE_LOGGER:{ BTIF_INFO_FUNC ("enable btif log function for both Tx and Rx\n"); btif_log_buf_enable(&p_btif->tx_log); btif_log_buf_enable(&p_btif->rx_log); } break; case BTIF_DUMP_LOG:{ BTIF_INFO_FUNC("dump btif log for both Tx and Rx\n"); btif_log_buf_dmp_out(&p_btif->tx_log); btif_log_buf_dmp_out(&p_btif->rx_log); } break; case BTIF_CLR_LOG:{ BTIF_INFO_FUNC("clear btif log for both Tx and Rx\n"); btif_log_buf_reset(&p_btif->tx_log); btif_log_buf_reset(&p_btif->rx_log); } break; case BTIF_DUMP_BTIF_REG: btif_dump_reg(p_btif, REG_ALL); break; case BTIF_DUMP_BTIF_IRQ: btif_dump_reg(p_btif, REG_IRQ); break; case BTIF_ENABLE_RT_LOG: BTIF_INFO_FUNC ("enable btif real time log for both Tx and Rx\n"); btif_log_output_enable(&p_btif->tx_log); btif_log_output_enable(&p_btif->rx_log); break; case BTIF_DISABLE_RT_LOG: BTIF_INFO_FUNC ("disable btif real time log for both Tx and Rx\n"); btif_log_output_disable(&p_btif->tx_log); btif_log_output_disable(&p_btif->rx_log); break; case BTIF_DUMP_DMA_VFIFO: btif_dump_dma_vfifo(p_btif); break; default: BTIF_INFO_FUNC("not supported flag:%d\n", flag); i_ret = -2; break; } return i_ret; } EXPORT_SYMBOL(mtk_wcn_btif_dbg_ctrl); bool mtk_wcn_btif_parser_wmt_evt(unsigned long u_id, const char *sub_str, unsigned int str_len) { bool b_ret = false; struct _mtk_btif_ *p_btif = NULL; p_btif = btif_exp_srh_id(u_id); if (p_btif == NULL) return E_BTIF_INVAL_PARAM; b_ret = btif_parser_wmt_evt(p_btif, sub_str, str_len); BTIF_INFO_FUNC("parser wmt evt %s\n", b_ret ? "ok" : "fail"); return b_ret; } EXPORT_SYMBOL(mtk_wcn_btif_parser_wmt_evt); /**********End of Debug Purpose API declearation**********/ int btif_open_no_id(void) { int i_ret = 0; struct _mtk_btif_ *p_btif = &g_btif[0]; i_ret = btif_open(p_btif); if (i_ret) BTIF_ERR_FUNC("btif_open failed, i_ret(%d)\n", i_ret); else BTIF_INFO_FUNC("btif_open succeed\n"); return i_ret; } int btif_close_no_id(void) { int i_ret = 0; struct _mtk_btif_ *p_btif = &g_btif[0]; i_ret = btif_close(p_btif); if (i_ret) BTIF_ERR_FUNC("btif_close failed, i_ret(%d)\n", i_ret); else BTIF_INFO_FUNC("btif_close succeed\n"); return i_ret; } int btif_write_no_id(const unsigned char *p_buf, unsigned int len) { int i_ret = -1; struct _mtk_btif_ *p_btif = &g_btif[0]; BTIF_DBG_FUNC("++"); if (p_buf == NULL) { BTIF_ERR_FUNC("invalid p_buf (0x%p)\n", p_buf); return E_BTIF_INVAL_PARAM; } if ((len == 0) || (len > BTIF_MAX_LEN_PER_PKT)) { BTIF_ERR_FUNC("invalid buffer length(%d)\n", len); return E_BTIF_INVAL_PARAM; } i_ret = btif_send_data(p_btif, p_buf, len); BTIF_DBG_FUNC("--, i_ret:%d\n", i_ret); return i_ret; } int btif_dpidle_ctrl_no_id(enum _ENUM_BTIF_DPIDLE_ en_flag) { int i_ret = -1; struct _mtk_btif_ *p_btif = &g_btif[0]; if (en_flag == BTIF_DPIDLE_DISABLE) i_ret = btif_exit_dpidle(p_btif); else i_ret = btif_enter_dpidle(p_btif); return i_ret; } int btif_wakeup_consys_no_id(void) { int i_ret = -1; struct _mtk_btif_ *p_btif = &g_btif[0]; /*i_ret = hal_btif_raise_wak_sig(p_btif->p_btif_info);*/ i_ret = btif_raise_wak_signal(p_btif); return i_ret; } int btif_loopback_ctrl_no_id(enum _ENUM_BTIF_LPBK_MODE_ enable) { int i_ret = -1; struct _mtk_btif_ *p_btif = &g_btif[0]; i_ret = btif_lpbk_ctrl(p_btif, enable == BTIF_LPBK_ENABLE ? true : false); return i_ret; } int btif_dbg_ctrl_no_id(enum _ENUM_BTIF_DBG_ID_ flag) { int i_ret = -1; struct _mtk_btif_ *p_btif = &g_btif[0]; i_ret = 0; switch (flag) { case BTIF_DISABLE_LOGGER:{ BTIF_INFO_FUNC ("disable btif log function for both Tx and Rx\n"); btif_log_buf_disable(&p_btif->tx_log); btif_log_buf_disable(&p_btif->rx_log); } break; case BTIF_ENABLE_LOGGER:{ BTIF_INFO_FUNC ("enable btif log function for both Tx and Rx\n"); btif_log_buf_enable(&p_btif->tx_log); btif_log_buf_enable(&p_btif->rx_log); } break; case BTIF_DUMP_LOG:{ BTIF_INFO_FUNC("dump btif log for both Tx and Rx\n"); btif_log_buf_dmp_out(&p_btif->tx_log); btif_log_buf_dmp_out(&p_btif->rx_log); } break; case BTIF_CLR_LOG:{ BTIF_INFO_FUNC("clear btif log for both Tx and Rx\n"); btif_log_buf_reset(&p_btif->tx_log); btif_log_buf_reset(&p_btif->rx_log); } break; case BTIF_DUMP_BTIF_REG: btif_dump_reg(p_btif, REG_ALL); break; case BTIF_DUMP_BTIF_IRQ: btif_dump_reg(p_btif, REG_IRQ); break; case BTIF_ENABLE_RT_LOG: BTIF_INFO_FUNC ("enable btif real time log for both Tx and Rx\n"); btif_log_output_enable(&p_btif->tx_log); btif_log_output_enable(&p_btif->rx_log); break; case BTIF_DISABLE_RT_LOG: BTIF_INFO_FUNC ("disable btif real time log for both Tx and Rx\n"); btif_log_output_disable(&p_btif->tx_log); btif_log_output_disable(&p_btif->rx_log); break; default: BTIF_INFO_FUNC("not supported flag:%d\n", flag); i_ret = -2; break; } return i_ret; } int mtk_btif_exp_open_test(void) { int i_ret = 0; i_ret = btif_open_no_id(); if (i_ret < 0) { BTIF_INFO_FUNC("mtk_wcn_btif_open failed\n"); return -1; } BTIF_INFO_FUNC("mtk_wcn_btif_open succeed\n"); return i_ret; } int mtk_btif_exp_close_test(void) { int i_ret = 0; i_ret = btif_close_no_id(); if (i_ret < 0) { BTIF_INFO_FUNC("mtk_wcn_btif_close failed\n"); return -1; } BTIF_INFO_FUNC("mtk_wcn_btif_close succeed\n"); return i_ret; } int mtk_btif_exp_write_test(void) { return mtk_btif_exp_write_stress_test(100, 10); } int mtk_btif_exp_write_stress_test(unsigned int length, unsigned int max_loop) { #define BUF_LEN 1024 int i_ret = 0; int idx = 0; int buf_len = length > BUF_LEN ? BUF_LEN : length; int loop = max_loop > 1000000 ? 1000000 : max_loop; unsigned char *buffer; buffer = kmalloc(BUF_LEN, GFP_KERNEL); if (!buffer) { BTIF_ERR_FUNC("btif tester kmalloc failed\n"); return -1; } for (idx = 0; idx < buf_len; idx++) /* btif_stress_test_buf[idx] = BUF_LEN -idx; */ *(buffer + idx) = idx % 255; i_ret = btif_loopback_ctrl_no_id(BTIF_LPBK_ENABLE); BTIF_INFO_FUNC("mtk_wcn_btif_loopback_ctrl returned %d\n", i_ret); while (loop--) { i_ret = btif_write_no_id(buffer, buf_len); BTIF_INFO_FUNC("mtk_wcn_btif_write left loop:%d, i_ret:%d\n", loop, i_ret); if (i_ret != buf_len) { BTIF_INFO_FUNC("target len %d, sent len: %d\n", buf_len, i_ret); break; } buf_len--; if (buf_len <= 0) buf_len = length > BUF_LEN ? BUF_LEN : length; } kfree(buffer); return i_ret; } int mtk_btif_exp_suspend_test(void) { int i_ret = 0; struct _mtk_btif_ *p_btif = &g_btif[0]; i_ret = _btif_suspend(p_btif); return i_ret; } int mtk_btif_exp_restore_noirq_test(void) { int i_ret = 0; struct _mtk_btif_ *p_btif = &g_btif[0]; i_ret = _btif_restore_noirq(p_btif); return i_ret; } int mtk_btif_exp_clock_ctrl(int en) { int i_ret = 0; struct _mtk_btif_ *p_btif = &g_btif[0]; i_ret = btif_clock_ctrl(p_btif, en); return i_ret; } int mtk_btif_exp_resume_test(void) { int i_ret = 0; struct _mtk_btif_ *p_btif = &g_btif[0]; i_ret = _btif_resume(p_btif); return i_ret; } int mtk_btif_exp_enter_dpidle_test(void) { return btif_dpidle_ctrl_no_id(BTIF_DPIDLE_ENABLE); } int mtk_btif_exp_exit_dpidle_test(void) { return btif_dpidle_ctrl_no_id(BTIF_DPIDLE_DISABLE); } int mtk_btif_exp_log_debug_test(int flag) { int i_ret = 0; i_ret = btif_dbg_ctrl_no_id(flag); return i_ret; } void mtk_btif_read_cpu_sw_rst_debug_exp(void) { mtk_btif_read_cpu_sw_rst_debug(); } int mtk_btif_exp_rx_has_pending_data(unsigned long u_id) { struct _mtk_btif_ *p_btif = NULL; int has_pending_data = 0; p_btif = btif_exp_srh_id(u_id); if (p_btif == NULL) { BTIF_ERR_FUNC("parameter invalid\n"); return E_BTIF_INVAL_PARAM; } /* Lock the data path to ensure that the current data path is * not processing data. If fail to get lock, it means rx data * path is busy and we assume there has pending data to avoid * thread is blocked here. */ if (btif_rx_data_path_lock(p_btif)) return 1; has_pending_data = btif_rx_buf_has_pending_data(p_btif); if (has_pending_data == 0) has_pending_data = btif_rx_dma_has_pending_data(p_btif); btif_rx_data_path_unlock(p_btif); return has_pending_data; } EXPORT_SYMBOL(mtk_btif_exp_rx_has_pending_data); int mtk_btif_exp_tx_has_pending_data(unsigned long u_id) { struct _mtk_btif_ *p_btif = NULL; p_btif = btif_exp_srh_id(u_id); if (p_btif == NULL) { BTIF_ERR_FUNC("E_BTIF_INVAL_PARAM\n"); return E_BTIF_INVAL_PARAM; } return btif_tx_dma_has_pending_data(p_btif); } EXPORT_SYMBOL(mtk_btif_exp_tx_has_pending_data); int mtk_btif_is_tx_complete(unsigned long u_id) { struct _mtk_btif_ *p_btif = NULL; p_btif = btif_exp_srh_id(u_id); if (p_btif == NULL) { BTIF_ERR_FUNC("E_BTIF_INVAL_PARAM\n"); return E_BTIF_INVAL_PARAM; } return btif_is_tx_complete(p_btif); } EXPORT_SYMBOL(mtk_btif_is_tx_complete); struct task_struct *mtk_btif_exp_rx_thread_get(unsigned long u_id) { struct _mtk_btif_ *p_btif = NULL; p_btif = btif_exp_srh_id(u_id); if (p_btif == NULL) { BTIF_ERR_FUNC("E_BTIF_INVAL_PARAM\n"); return NULL; } return btif_rx_thread_get(p_btif); } EXPORT_SYMBOL(mtk_btif_exp_rx_thread_get); /************End of Function**********/