Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit eafb2811 authored by Kshitij's avatar Kshitij Committed by Sahil Sonar
Browse files

linux-mtk-4.19: Port and redo MediaTek kernel_modules

- Having them in the kernel source lets out-of-tree builds
  compile modules easily.

Change-Id: I08c9ecafc3a647333053c75046d6a4fee5bf8a65
parent 450b969a
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -6,6 +6,7 @@ subdir-ccflags-y += -I$(srctree)/drivers/misc/mediatek/include/mt-plat/
subdir-ccflags-y += -I$(srctree)/drivers/mmc/host/mediatek/$(MTK_PLATFORM)

obj-$(CONFIG_MTK_MET) += met_drv/
obj-y += met_drv_v2/
obj-$(CONFIG_MTK_BASE_POWER) += base/
obj-$(CONFIG_MTK_PWM)	    += pwm/
obj-$(CONFIG_MTK_IRTX_PWM_SUPPORT) += irtx/
@@ -119,3 +120,4 @@ obj-$(CONFIG_MTK_GIC_EXT) += ext_gic/
obj-$(CONFIG_MTK_SYS_CIRQ) += cirq/
obj-$(CONFIG_MTK_SECURITY_SW_SUPPORT) += masp/
obj-y += rps/
obj-$(CONFIG_MTK_FPSGO_V3) += fpsgo_cus/
+14 −6
Original line number Diff line number Diff line
@@ -37,6 +37,13 @@ ifneq ($(KERNELRELEASE),)
    ifeq ($(CONFIG_MTK_COMBO), y)
        ccflags-y += -D CFG_CONNADP_BUILD_IN
    endif

    # for gen4m options
    export CONFIG_MTK_COMBO_WIFI_HIF=axi
    export MTK_COMBO_CHIP=CONNAC
    export WLAN_CHIP_ID=6765
    export MTK_ANDROID_WMT=y

    # Do build-in for Makefile checking
    # export CONFIG_WLAN_DRV_BUILD_IN=y

@@ -72,12 +79,6 @@ ifneq ($(KERNELRELEASE),)
        $(shell ln -s $(ABS_PATH_TO_WLAN_CHR_DRV) $(srctree)/$(src)/wmt_chrdev_wifi)
        $(shell ln -s $(ABS_PATH_TO_WLAN_DRV)     $(srctree)/$(src)/wlan_drv_gen4m)

        # for gen4m options
        export CONFIG_MTK_COMBO_WIFI_HIF=axi
        export MTK_COMBO_CHIP=CONNAC
        export WLAN_CHIP_ID=6765
        export MTK_ANDROID_WMT=y

        # Do build-in for xxx.c checking
        subdir-ccflags-y += -D MTK_WCN_REMOVE_KERNEL_MODULE
        subdir-ccflags-y += -D MTK_WCN_BUILT_IN_DRIVER
@@ -86,6 +87,13 @@ ifneq ($(KERNELRELEASE),)
        obj-y += wlan_drv_gen4m/
    endif

    obj-$(CONFIG_MTK_COMBO) += common/
    obj-$(CONFIG_MTK_COMBO_WIFI) += wlan/adaptor/
    obj-$(CONFIG_MTK_COMBO_CHIP_CONSYS_6765) += wlan/core/gen4m/
    obj-$(CONFIG_MTK_BTIF) += bt/mt66xx/legacy/
    obj-$(CONFIG_MTK_COMBO_GPS) += gps/
    obj-$(CONFIG_MTK_FMRADIO) += fmradio/

# Otherwise we were called directly from the command line;
# invoke the kernel build system.
else
+49 −0
Original line number Diff line number Diff line
MTK_PLATFORM := $(subst ",,$(CONFIG_MTK_PLATFORM))
###############################################################################
# Bluetooth character device driver

ifneq ($(CFG_BT_PM_QOS_CONTROL),)
    $(warning set PM_QOS_CONTROL=1)
    ccflags-y += -D PM_QOS_CONTROL=1
else
    ccflags-y += -D PM_QOS_CONTROL=0
endif

# Force build fail on modpost warning
KBUILD_MODPOST_FAIL_ON_WARNINGS := y
###############################################################################
# To add WMT dependent Macro and header file, will be removed later

ccflags-y += -D MTK_WCN_WMT_STP_EXP_SYMBOL_ABSTRACT
ccflags-y += -I$(srctree)/drivers/misc/mediatek/include
ccflags-y += -I$(srctree)/drivers/misc/mediatek/include/mt-plat
ccflags-y += -I$(srctree)/drivers/misc/mediatek/include/mt-plat/$(MTK_PLATFORM)/include

ifeq ($(CONFIG_MTK_CONN_LTE_IDC_SUPPORT),y)
    ccflags-y += -D WMT_IDC_SUPPORT=1
else
    ccflags-y += -D WMT_IDC_SUPPORT=0
endif

###############################################################################
# To include BT driver dependent header file

WMT_SRC_FOLDER := $(srctree)/drivers/misc/mediatek/connectivity/common
ccflags-y += -I$(WMT_SRC_FOLDER)/common_main/include
ccflags-y += -I$(WMT_SRC_FOLDER)/common_main/linux/include
ifneq ($(CONFIG_MTK_CONNSYS_DEDICATED_LOG_PATH),)
ccflags-y += -I$(WMT_SRC_FOLDER)/debug_utility
endif

###############################################################################

MODULE_NAME := bt_drv
obj-m += $(MODULE_NAME).o

ccflags-y += -D CREATE_NODE_DYNAMIC=1

$(MODULE_NAME)-objs += stp_chrdev_bt.o
$(MODULE_NAME)-objs += dbg_bt.o
ifneq ($(CONFIG_MTK_CONNSYS_DEDICATED_LOG_PATH),)
$(MODULE_NAME)-objs += fw_log_bt.o
endif
+138 −0
Original line number Diff line number Diff line
/*
*  Copyright (C) 2016 MediaTek Inc.
*
* This program is free software: you can redistribute it and/or modify it under the terms of the
* GNU General Public License version 2 as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with this program.
* If not, see <http://www.gnu.org/licenses/>.
*/

#ifndef _BT_EXP_H_
#define _BT_EXP_H_

#include <linux/init.h>
#include <linux/module.h>
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/cdev.h>
#include <linux/sched.h>
#include <asm/current.h>
#include <linux/uaccess.h>
#include <linux/fcntl.h>
#include <linux/poll.h>
#include <linux/time.h>
#include <linux/delay.h>
#include <linux/device.h>
#include <linux/printk.h>
#include <linux/uio.h>
#include <linux/workqueue.h>

#include "wmt_exp.h"
#include "stp_exp.h"


#define TRUE   1
#define FALSE  0

/* Flags to control BT FW log flow */
#define OFF 0x00
#define ON  0xff

#define PFX                     "[MTK-BT]"
#define BT_LOG_DBG              4
#define BT_LOG_INFO             3
#define BT_LOG_WARN             2
#define BT_LOG_ERR              1
#define RAW_MAX_BYTES           30

static uint8_t raw_buf[RAW_MAX_BYTES * 5 + 10];
extern UINT32 gBtDbgLevel;

#define BT_LOG_PRT_DBG(fmt, arg...)	\
	do { if (gBtDbgLevel >= BT_LOG_DBG) pr_info(PFX "%s: " fmt, __func__, ##arg); } while (0)
#define BT_LOG_PRT_INFO(fmt, arg...)	\
	do { if (gBtDbgLevel >= BT_LOG_INFO) pr_info(PFX "%s: " fmt, __func__, ##arg); } while (0)
#define BT_LOG_PRT_WARN(fmt, arg...)	\
	do { if (gBtDbgLevel >= BT_LOG_WARN) pr_info(PFX "%s: " fmt, __func__, ##arg); } while (0)
#define BT_LOG_PRT_ERR(fmt, arg...)	\
	do { if (gBtDbgLevel >= BT_LOG_ERR) pr_info(PFX "%s: " fmt, __func__, ##arg); } while (0)
#define BT_LOG_PRT_INFO_RATELIMITED(fmt, arg...)	\
	do { if (gBtDbgLevel >= BT_LOG_ERR) pr_info_ratelimited(PFX "%s: " fmt, __func__, ##arg); } while (0)

#define BT_LOG_PRT_DBG_RAW(p, l, fmt, ...)						\
			do {	\
				if (gBtDbgLevel >= BT_LOG_DBG) { \
					int cnt_ = 0;	\
					int len_ = (l <= RAW_MAX_BYTES ? l : RAW_MAX_BYTES);	\
					const unsigned char *ptr = p;	\
					for (cnt_ = 0; cnt_ < len_; ++cnt_) {	\
						if (snprintf(raw_buf+5*cnt_, 6, "0x%02X ", ptr[cnt_]) < 0) {	\
							pr_info("snprintf error\n");	\
							break;	\
						}	\
					}	\
					raw_buf[5*cnt_] = '\0'; \
					if (l <= RAW_MAX_BYTES) {	\
						pr_info(PFX" "fmt"%s\n", ##__VA_ARGS__, raw_buf);	\
					} else {	\
						pr_info(PFX" "fmt"%s (prtail)\n", ##__VA_ARGS__, raw_buf); \
					}	\
				}	\
			} while (0)

#define BT_LOG_PRT_INFO_RAW(p, l, fmt, ...)						\
		do {	\
			if (gBtDbgLevel >= BT_LOG_INFO) {	\
				int cnt_ = 0;	\
				int len_ = (l <= RAW_MAX_BYTES ? l : RAW_MAX_BYTES);	\
				const unsigned char *ptr = p;	\
				for (cnt_ = 0; cnt_ < len_; ++cnt_) {	\
					if (snprintf(raw_buf+5*cnt_, 6, "0x%02X ", ptr[cnt_]) < 0) {	\
						pr_info("snprintf error\n");	\
						break;	\
					}	\
				}	\
				raw_buf[5*cnt_] = '\0'; \
				if (l <= RAW_MAX_BYTES) {	\
					pr_info(PFX" "fmt"%s\n", ##__VA_ARGS__, raw_buf);	\
				} else {	\
					pr_info(PFX" "fmt"%s (prtail)\n", ##__VA_ARGS__, raw_buf); \
				}	\
			}	\
		} while (0)

struct bt_dbg_st {
	bool trx_enable;
	uint16_t trx_opcode;
	struct completion trx_comp;
	void(*trx_cb) (char *buf, int len);
	int rx_len;
	char rx_buf[64];
};

struct pm_qos_ctrl {
	struct semaphore sem;
	struct workqueue_struct *task;
	struct delayed_work work;
	u_int8_t is_hold;
};

/* *****************************************************************************************
 * BT Logger Tool will send 3 levels(Low, SQC and Debug)
 * Driver will not check its range so we can provide capability of extention.
 ******************************************************************************************/
#define DEFAULT_LEVEL 0x02 /* 0x00:OFF, 0x01: LOW POWER, 0x02: SQC, 0x03: DEBUG */

extern int  fw_log_bt_init(void);
extern void fw_log_bt_exit(void);
extern void bt_state_notify(UINT32 on_off);
extern ssize_t send_hci_frame(const PUINT8 buf, size_t count);

#endif
+367 −0
Original line number Diff line number Diff line
/*  SPDX-License-Identifier: GPL-2.0 */
/*
 * Copyright (c) 2019 MediaTek Inc.
 */
#include <linux/io.h>
#include <linux/uaccess.h>
#include <linux/proc_fs.h>
#include "bt.h"

/*******************************************************************************
*				 C O N S T A N T S
********************************************************************************
*/
#define BT_DBG_PROCNAME "driver/bt_dbg"
#define BUF_LEN_MAX 384
#define BT_DBG_DUMP_BUF_SIZE 1024
#define BT_DBG_PASSWD "4w2T8M65K5?2af+a "
#define BT_DBG_USER_TRX_PREFIX "[user-trx] "

/*******************************************************************************
*			       D A T A	 T Y P E S
********************************************************************************
*/
typedef int(*BT_DEV_DBG_FUNC) (int par1, int par2, int par3);
typedef struct {
  BT_DEV_DBG_FUNC func;
  bool turn_off_availavle; // function can be work when bt off
} tBT_DEV_DBG_STRUCT;

/*******************************************************************************
*			      P U B L I C   D A T A
********************************************************************************
*/

/*******************************************************************************
*                  F U N C T I O N   D E C L A R A T I O N S
********************************************************************************
*/
static int bt_dbg_get_bt_state(int par1, int par2, int par3);
static int bt_dbg_setlog_level(int par1, int par2, int par3);

/*******************************************************************************
*			     P R I V A T E   D A T A
********************************************************************************
*/
extern struct bt_dbg_st g_bt_dbg_st;
extern UINT32 gBtDbgLevel;
static struct proc_dir_entry *g_bt_dbg_entry;
static struct mutex g_bt_lock;
static char g_bt_dump_buf[BT_DBG_DUMP_BUF_SIZE];
static char *g_bt_dump_buf_ptr;
static int g_bt_dump_buf_len;
static bool g_bt_turn_on = FALSE;
static bool g_bt_dbg_enable = FALSE;

static const tBT_DEV_DBG_STRUCT bt_dev_dbg_struct[] = {
	[0xb] = {bt_dbg_setlog_level,		TRUE},
	[0xe] = {bt_dbg_get_bt_state,		TRUE},
};

/*******************************************************************************
*			       F U N C T I O N S
********************************************************************************
*/

void _bt_dbg_reset_dump_buf(void)
{
	memset(g_bt_dump_buf, '\0', BT_DBG_DUMP_BUF_SIZE);
	g_bt_dump_buf_ptr = g_bt_dump_buf;
	g_bt_dump_buf_len = 0;
}

int bt_dbg_get_bt_state(int par1, int par2, int par3)
{
	// 0x01: bt on, 0x00: bt off
	BT_LOG_PRT_INFO("g_bt_turn_on[%d]\n", g_bt_turn_on);
	_bt_dbg_reset_dump_buf();
	g_bt_dump_buf[0] = g_bt_turn_on;
	g_bt_dump_buf[1] = '\0';
	g_bt_dump_buf_len = 2;
	return 0;
}

int bt_dbg_setlog_level(int par1, int par2, int par3)
{
	if (par2 < BT_LOG_ERR || par2 > BT_LOG_DBG) {
		gBtDbgLevel = BT_LOG_INFO;
	} else {
		gBtDbgLevel = par2;
	}
	BT_LOG_PRT_INFO("gBtDbgLevel = %d\n", gBtDbgLevel);
	return 0;
}

ssize_t bt_dbg_read(struct file *filp, char __user *buf, size_t count, loff_t *f_pos)
{
	int ret = 0;
	int dump_len;

	ret = mutex_lock_killable(&g_bt_lock);
	if (ret) {
		BT_LOG_PRT_ERR("dump_lock fail!!\n");
		return ret;
	}

	if (g_bt_dump_buf_len == 0)
		goto exit;

	if (*f_pos == 0)
		g_bt_dump_buf_ptr = g_bt_dump_buf;

	dump_len = g_bt_dump_buf_len >= count ? count : g_bt_dump_buf_len;
	ret = copy_to_user(buf, g_bt_dump_buf_ptr, dump_len);
	if (ret) {
		BT_LOG_PRT_ERR("copy to dump info buffer failed, ret:%d\n", ret);
		ret = -EFAULT;
		goto exit;
	}

	*f_pos += dump_len;
	g_bt_dump_buf_len -= dump_len;
	g_bt_dump_buf_ptr += dump_len;
	BT_LOG_PRT_INFO("after read, wmt for dump info buffer len(%d)\n", g_bt_dump_buf_len);

	ret = dump_len;
exit:

	mutex_unlock(&g_bt_lock);
	return ret;
}

int _osal_strtol(const char *str, unsigned int adecimal, long *res)
{
	if (sizeof(long) == 4)
		return kstrtou32(str, adecimal, (unsigned int *) res);
	else
		return kstrtol(str, adecimal, res);
}

void bt_dbg_user_trx_cb(char *buf, int len)
{
	unsigned char *ptr = g_bt_dbg_st.rx_buf;
	unsigned int i = 0, evt_len = 0;
	int ret = 0;

	/* 1. bluedroid use partial read, this callback will enter several times
	   2. this function read and parse the command_complete event */
	memcpy(&g_bt_dbg_st.rx_buf[g_bt_dbg_st.rx_len], buf, len);
	g_bt_dbg_st.rx_len += len;

	// check the complete packet is read out by bluedroid
	if(g_bt_dbg_st.rx_len != (g_bt_dbg_st.rx_buf[2] + 3))
		return;

	// if this event is not the desire one, skip and reset buffer
	if((g_bt_dbg_st.rx_buf[4] + (g_bt_dbg_st.rx_buf[5] << 8)) != g_bt_dbg_st.trx_opcode) {
		g_bt_dbg_st.rx_len = 0;
		memset(g_bt_dbg_st.rx_buf, 0, sizeof(g_bt_dbg_st.rx_buf));
		return;
	}

	// desire rx event is received, write to read buffer as string
	evt_len = g_bt_dbg_st.rx_len;
	BT_LOG_PRT_INFO_RAW(g_bt_dbg_st.rx_buf, evt_len, "%s: len[%ud], RxEvt: ", __func__, evt_len);
	if(evt_len * 5 + 2 > BT_DBG_DUMP_BUF_SIZE)
		return;

	_bt_dbg_reset_dump_buf();
	for (i = 0; i < evt_len; i++) {
		ret = snprintf(g_bt_dump_buf + 5*i, 6, "0x%02X ", ptr[i]);
		if (ret < 0)  {
			BT_LOG_PRT_ERR("error snprintf return value = [%d]\n", ret);
			return;
		}
	}

	g_bt_dump_buf[5*evt_len] = '\n';
	g_bt_dump_buf[5*evt_len + 1] = '\0';
	g_bt_dump_buf_len = 5*evt_len + 1;

	// complete trx process
	complete(&g_bt_dbg_st.trx_comp);
}

void bt_dbg_user_trx_proc(char *cmd_raw)
{
#define LEN_64 64
	unsigned char hci_cmd[LEN_64];
	unsigned int len = 0;
	long tmp = 0;
	char *ptr = NULL, *pRaw = NULL;

	// Parse command raw data
	memset(hci_cmd, 0, sizeof(hci_cmd));
	pRaw = cmd_raw;
	ptr = cmd_raw;
	while(*ptr != '\0' && pRaw != NULL) {
		if (len > LEN_64 - 1) {
			BT_LOG_PRT_INFO("%s: skip since cmd length exceed!", __func__);
			return;
		}
		ptr = strsep(&pRaw, " ");
		if (ptr != NULL) {
			_osal_strtol(ptr, 16, &tmp);
			hci_cmd[len++] = (unsigned char)tmp;
		}
	}

	// Initialize rx variables
	g_bt_dbg_st.rx_len = 0;
	g_bt_dbg_st.trx_opcode = hci_cmd[1] + (hci_cmd[2] << 8);
	memset(g_bt_dbg_st.rx_buf, 0, sizeof(g_bt_dbg_st.rx_buf));
	BT_LOG_PRT_INFO_RAW(hci_cmd, len, "%s: len[%ud], TxCmd: ", __func__, len);

	// Send command and wait for command_complete event
	g_bt_dbg_st.trx_enable = TRUE;
	send_hci_frame(hci_cmd, len);
	if (!wait_for_completion_timeout(&g_bt_dbg_st.trx_comp, msecs_to_jiffies(2000)))
		BT_LOG_PRT_ERR("%s: wait event timeout!", __func__);
	g_bt_dbg_st.trx_enable = FALSE;
}

ssize_t bt_dbg_write(struct file *filp, const char __user *buffer, size_t count, loff_t *f_pos)
{
	bool is_passwd = FALSE, is_turn_on = FALSE;
	size_t len = count;
	char buf[256], *pBuf;
	int x = 0, y = 0, z = 0;
	long res = 0;
	char* pToken = NULL;
	char* pDelimiter = " \t";

	if (len <= 0 || len >= sizeof(buf)) {
		BT_LOG_PRT_ERR("input handling fail!\n");
		len = sizeof(buf) - 1;
		return -1;
	}

	memset(buf, 0, sizeof(buf));
	if (copy_from_user(buf, buffer, len))
		return -EFAULT;
	buf[len] = '\0';
	BT_LOG_PRT_INFO("g_bt_turn_on[%d], dbg_enable[%d], len[%d], data = %s\n",
		g_bt_turn_on, g_bt_dbg_enable, (int)len, buf);

	/* Check debug function is enabled or not
	 *   - not enable yet: user should enable it
	 *   - already enabled: user can disable it
	 */
	if (len > strlen(BT_DBG_PASSWD) &&
		0 == memcmp(buf, BT_DBG_PASSWD, strlen(BT_DBG_PASSWD))) {
		is_passwd = TRUE;
		if (0 == memcmp(buf + strlen(BT_DBG_PASSWD), "ON", strlen("ON")))
			is_turn_on = TRUE;
	}
	if(!g_bt_dbg_enable) {
		if(is_passwd && is_turn_on)
			g_bt_dbg_enable = TRUE;
		return len;
	} else {
		if(is_passwd && !is_turn_on) {
			g_bt_dbg_enable = FALSE;
			return len;
		}
	}

	/* Mode 1: User trx flow: send command, get response */
	if (0 == memcmp(buf, BT_DBG_USER_TRX_PREFIX, strlen(BT_DBG_USER_TRX_PREFIX))) {
		if(!g_bt_turn_on) // only work when bt on
			return len;
		buf[len - 1] = '\0';
		bt_dbg_user_trx_proc(buf + strlen(BT_DBG_USER_TRX_PREFIX));
		return len;
	}

	/* Mode 2: Debug cmd flow, parse three parameters */
	pBuf = buf;
	pToken = strsep(&pBuf, pDelimiter);
	if (pToken != NULL) {
		_osal_strtol(pToken, 16, &res);
		x = (int)res;
	} else {
		x = 0;
	}

	pToken = strsep(&pBuf, "\t\n ");
	if (pToken != NULL) {
		_osal_strtol(pToken, 16, &res);
		y = (int)res;
		BT_LOG_PRT_INFO("y = 0x%08x\n", y);
	} else {
		y = 3000;
		/*efuse, register read write default value */
		if (0x5 == x || 0x6 == x)
			y = 0x80000000;
	}

	pToken = strsep(&pBuf, "\t\n ");
	if (pToken != NULL) {
		_osal_strtol(pToken, 16, &res);
		z = (int)res;
	} else {
		z = 10;
		/*efuse, register read write default value */
		if (0x5 == x || 0x6 == x)
			z = 0xffffffff;
	}

	BT_LOG_PRT_INFO("x(0x%08x), y(0x%08x), z(0x%08x)\n", x, y, z);
	if (ARRAY_SIZE(bt_dev_dbg_struct) > x && NULL != bt_dev_dbg_struct[x].func) {
		if(!g_bt_turn_on && !bt_dev_dbg_struct[x].turn_off_availavle) {
			BT_LOG_PRT_WARN("command id(0x%08x) only work when bt on!\n", x);
		} else {
			(*bt_dev_dbg_struct[x].func) (x, y, z);
		}
	} else {
		BT_LOG_PRT_WARN("command id(0x%08x) no handler defined!\n", x);
	}

	return len;
}

int bt_dev_dbg_init(void)
{
	int i_ret = 0;
	static const struct file_operations bt_dbg_fops = {
		.owner = THIS_MODULE,
		.read = bt_dbg_read,
		.write = bt_dbg_write,
	};

	// initialize debug function struct
	g_bt_dbg_st.trx_enable = FALSE;
	g_bt_dbg_st.trx_opcode = 0;
	g_bt_dbg_st.trx_cb = bt_dbg_user_trx_cb;
	init_completion(&g_bt_dbg_st.trx_comp);

	g_bt_dbg_entry = proc_create(BT_DBG_PROCNAME, 0664, NULL, &bt_dbg_fops);
	if (g_bt_dbg_entry == NULL) {
		BT_LOG_PRT_ERR("Unable to create [%s] bt proc entry\n", BT_DBG_PROCNAME);
		i_ret = -1;
	}

	mutex_init(&g_bt_lock);

	BT_LOG_PRT_INFO("create [%s] done\n", BT_DBG_PROCNAME);
	return i_ret;
}

int bt_dev_dbg_deinit(void)
{
	mutex_destroy(&g_bt_lock);

	if (g_bt_dbg_entry != NULL) {
		proc_remove(g_bt_dbg_entry);
		g_bt_dbg_entry = NULL;
	}

	return 0;
}


int bt_dev_dbg_set_state(bool turn_on)
{
	g_bt_turn_on = turn_on;
	return 0;
}
Loading