示例#1
0
static VOID bt_cdev_rst_cb(ENUM_WMTDRV_TYPE_T src,
			   ENUM_WMTDRV_TYPE_T dst, ENUM_WMTMSG_TYPE_T type, PVOID buf, UINT32 sz)
{
	/*
	   Handle whole chip reset messages
	 */
	ENUM_WMTRSTMSG_TYPE_T rst_msg;

	if (sz <= sizeof(ENUM_WMTRSTMSG_TYPE_T)) {
		memcpy((PINT8) & rst_msg, (PINT8) buf, sz);
		BT_DBG_FUNC("src = %d, dst = %d, type = %d, buf = 0x%x sz = %d, max = %d\n", src,
			     dst, type, rst_msg, sz, WMTRSTMSG_RESET_MAX);
		if ((src == WMTDRV_TYPE_WMT) && (dst == WMTDRV_TYPE_BT)
		    && (type == WMTMSG_TYPE_RESET)) {
			if (rst_msg == WMTRSTMSG_RESET_START) {
				BT_INFO_FUNC("BT reset start!\n");
				rstflag = 1;
				wake_up_interruptible(&inq);

			} else if (rst_msg == WMTRSTMSG_RESET_END) {
				BT_INFO_FUNC("BT reset end!\n");
				rstflag = 2;
				wake_up_interruptible(&inq);
			}
		}
	} else {
		/* Invalid message format */
		BT_WARN_FUNC("Invalid message format!\n");
	}
}
示例#2
0
static VOID bt_cdev_rst_cb(ENUM_WMTDRV_TYPE_T src,
			   ENUM_WMTDRV_TYPE_T dst, ENUM_WMTMSG_TYPE_T type, PVOID buf, UINT32 sz)
{

	/*
	   To handle reset procedure please
	 */
	ENUM_WMTRSTMSG_TYPE_T rst_msg;

	BT_INFO_FUNC("sizeof(ENUM_WMTRSTMSG_TYPE_T) = %zd\n", sizeof(ENUM_WMTRSTMSG_TYPE_T));
	if (sz <= sizeof(ENUM_WMTRSTMSG_TYPE_T)) {
		memcpy((PINT8) &rst_msg, (PINT8) buf, sz);
		BT_INFO_FUNC("src = %d, dst = %d, type = %d, buf = 0x%x sz = %d, max = %d\n", src,
			     dst, type, rst_msg, sz, WMTRSTMSG_RESET_MAX);
		if ((src == WMTDRV_TYPE_WMT) && (dst == WMTDRV_TYPE_BT)
		    && (type == WMTMSG_TYPE_RESET)) {
			if (rst_msg == WMTRSTMSG_RESET_START) {
				BT_INFO_FUNC("BT restart start!\n");
				retflag = 1;
				wake_up_interruptible(&inq);
				/*reset_start message handling */

			} else if (rst_msg == WMTRSTMSG_RESET_END) {
				BT_INFO_FUNC("BT restart end!\n");
				retflag = 2;
				wake_up_interruptible(&inq);
				/*reset_end message handling */
			}
		}
	} else {
		/*message format invalid */
		BT_INFO_FUNC("message format invalid!\n");
	}
}
示例#3
0
ssize_t BT_read(struct file *filp, char __user *buf, size_t count, loff_t *f_pos)
{
	static int chip_reset_count;
	INT32 retval = 0;

	down(&rd_mtx);

	BT_DBG_FUNC("%s: count %zd pos %lld\n", __func__, count, *f_pos);
	if (rstflag) {
		if (rstflag == 1) {	/* Reset start */
			retval = -88;
			if ((chip_reset_count%500) == 0)
				BT_INFO_FUNC("%s: detect whole chip reset start, %d\n", __func__, chip_reset_count);
			chip_reset_count++;
		} else if (rstflag == 2) {	/* Reset end */
			retval = -99;
			BT_INFO_FUNC("%s: detect whole chip reset end\n", __func__);
			chip_reset_count = 0;
		}
		goto OUT;
	}

	if (count > BT_BUFFER_SIZE) {
		count = BT_BUFFER_SIZE;
		BT_ERR_FUNC("%s: count > BT_BUFFER_SIZE\n", __func__);
	}

	retval = mtk_wcn_stp_receive_data(i_buf, count, BT_TASK_INDX);

	while (retval == 0) {	/* Got nothing, wait for STP's signal */
		/*
		* If nonblocking mode, return directly.
		* O_NONBLOCK is specified during open()
		*/
		if (filp->f_flags & O_NONBLOCK) {
			BT_DBG_FUNC("Non-blocking BT_read\n");
			retval = -EAGAIN;
			goto OUT;
		}

		BT_DBG_FUNC("%s: wait_event 1\n", __func__);
		wait_event(BT_wq, flag != 0);
		BT_DBG_FUNC("%s: wait_event 2\n", __func__);
		flag = 0;
		retval = mtk_wcn_stp_receive_data(i_buf, count, BT_TASK_INDX);
		BT_DBG_FUNC("%s: mtk_wcn_stp_receive_data returns %d\n", __func__, retval);
	}

	/* Got something from STP driver */
	if (copy_to_user(buf, i_buf, retval)) {
		retval = -EFAULT;
		goto OUT;
	}

OUT:
	up(&rd_mtx);
	BT_DBG_FUNC("%s: retval = %d\n", __func__, retval);
	return retval;
}
ssize_t BT_read(struct file *filp, char __user *buf, size_t count, loff_t *f_pos)
{
    int retval = 0;

    down(&rd_mtx);

    BT_DBG_FUNC("BT_read(): count %d pos %lld\n", count, *f_pos);
    if(retflag)
    {
        if (retflag == 1) //reset start
        {
            retval = -88;
            BT_INFO_FUNC("MT662x reset Read: start\n");
        }
        else if (retflag == 2) // reset end
        {
            retval = -99;
            BT_INFO_FUNC("MT662x reset Read: end\n");
        }
    goto OUT;
    }

    if(count > MTKSTP_BUFFER_SIZE)
    {
        count = MTKSTP_BUFFER_SIZE;
    }
    retval = mtk_wcn_stp_receive_data(i_buf, count, BT_TASK_INDX);

    while(retval == 0) // got nothing, wait for STP's signal
    {
        /*If nonblocking mode, return directly O_NONBLOCK is specified during open() */
        if (filp->f_flags & O_NONBLOCK){
            BT_DBG_FUNC("Non-blocking BT_read() \n");
            retval = -EAGAIN;
            goto OUT;
        }

        BT_DBG_FUNC("BT_read(): wait_event 1\n");
        wait_event(BT_wq, flag != 0);
        BT_DBG_FUNC("BT_read(): wait_event 2\n");
        flag = 0;
        retval = mtk_wcn_stp_receive_data(i_buf, count, BT_TASK_INDX);
        BT_DBG_FUNC("BT_read(): mtk_wcn_stp_receive_data() = %d\n", retval);
    }

    // we got something from STP driver
    if (copy_to_user(buf, i_buf, retval))
    {
        retval = -EFAULT;
        goto OUT;
    }

OUT:
    up(&rd_mtx);
    BT_DBG_FUNC("BT_read(): retval = %d\n", retval);
    return (retval);
}
示例#5
0
/* int BT_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg) */
long BT_unlocked_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
{
	INT32 retval = 0;
	MTK_WCN_BOOL bRet = MTK_WCN_BOOL_TRUE;

	ENUM_WMTHWVER_TYPE_T hw_ver_sym = WMTHWVER_INVALID;
	BT_DBG_FUNC("BT_ioctl(): cmd (%d)\n", cmd);

	switch (cmd) {
#if 0
	case 0:		/* enable/disable STP */
		/* George: STP is controlled by WMT only */
		/* mtk_wcn_stp_enable(arg); */
		break;
#endif
	case 1:		/* send raw data */
		BT_DBG_FUNC("BT_ioctl(): disable raw data from BT dev\n");
		retval = -EINVAL;
		break;
	case COMBO_IOC_BT_HWVER:
		/*get combo hw version */
		hw_ver_sym = mtk_wcn_wmt_hwver_get();

		BT_INFO_FUNC("BT_ioctl(): get hw version = %d, sizeof(hw_ver_sym) = %zd\n",
			     hw_ver_sym, sizeof(hw_ver_sym));
		if (copy_to_user((int __user *)arg, &hw_ver_sym, sizeof(hw_ver_sym)))
			retval = -EFAULT;

		break;

	case COMBO_IOCTL_FW_ASSERT:
		/* BT trigger fw assert for debug */
		BT_INFO_FUNC("BT Set fw assert......, reason:%lu\n", arg);
		bRet = mtk_wcn_wmt_assert(WMTDRV_TYPE_BT, arg);
		if (bRet == MTK_WCN_BOOL_TRUE) {
			BT_INFO_FUNC("BT Set fw assert OK\n");
			retval = 0;
		} else {
			BT_INFO_FUNC("BT Set fw assert Failed\n");
			retval = (-1000);
		}
		break;
	case COMBO_IOCTL_BT_IC_HW_VER:
		return mtk_wcn_wmt_ic_info_get(WMTCHIN_HWVER);
		break;
	case COMBO_IOCTL_BT_IC_FW_VER:
		return mtk_wcn_wmt_ic_info_get(WMTCHIN_FWVER);
		break;
	default:
		retval = -EFAULT;
		BT_DBG_FUNC("BT_ioctl(): unknown cmd (%d)\n", cmd);
		break;
	}

	return retval;
}
示例#6
0
ssize_t BT_write(struct file *filp, const char __user *buf, size_t count, loff_t *f_pos)
{
	INT32 retval = 0;
	INT32 written = 0;
	down(&wr_mtx);

	BT_DBG_FUNC("%s: count %zd pos %lld\n", __func__, count, *f_pos);
	if (retflag) {
		if (retflag == 1) {	/* reset start */
			retval = -88;
			BT_INFO_FUNC("MT662x reset Write: start\n");
		} else if (retflag == 2) {	/* reset end */
			retval = -99;
			BT_INFO_FUNC("MT662x reset Write: end\n");
		}
		goto OUT;
	}

	if (count > 0) {
		INT32 copy_size;

		if (count < BT_BUFFER_SIZE) {
			copy_size = count;
		} else {
			copy_size = BT_BUFFER_SIZE;
			BT_ERR_FUNC(" count > BT_BUFFER_SIZE\n");
		}

		if (copy_from_user(&o_buf[0], &buf[0], copy_size)) {
			retval = -EFAULT;
			goto OUT;
		}
		/* pr_warn("%02x ", val); */

		written = mtk_wcn_stp_send_data(&o_buf[0], copy_size, BT_TASK_INDX);
		if (0 == written) {
			retval = -ENOSPC;
			/*no windowspace is available, native process should not call BT_write with no delay at all */
			BT_ERR_FUNC
			    ("target packet length:%zd, write success length:%d, retval = %d.\n",
			     count, written, retval);
		} else {
			retval = written;
		}

	} else {
		retval = -EFAULT;
		BT_ERR_FUNC("target packet length:%zd is not allowed, retval = %d.\n", count, retval);
	}

OUT:
	up(&wr_mtx);
	return retval;
}
ssize_t BT_write(struct file *filp, const char __user *buf, size_t count, loff_t *f_pos)
{
    int retval = 0;
    int written = 0;
    down(&wr_mtx);

    BT_DBG_FUNC("%s: count %d pos %lld\n", __func__, count, *f_pos);
    if(retflag)
    {
        if (retflag == 1) //reset start
        {
            retval = -88;
            BT_INFO_FUNC("MT662x reset Write: start\n");
        }
        else if (retflag == 2) // reset end
        {
          retval = -99;
            BT_INFO_FUNC("MT662x reset Write: end\n");
        }
    goto OUT;
    }

    if (count > 0)
    {
        int copy_size = (count < MTKSTP_BUFFER_SIZE) ? count : MTKSTP_BUFFER_SIZE;
        if (copy_from_user(&o_buf[0], &buf[0], copy_size))
        {
            retval = -EFAULT;
            goto OUT;
        }
        //printk("%02x ", val);

        written = mtk_wcn_stp_send_data(&o_buf[0], copy_size, BT_TASK_INDX);
        if(0 == written)
        {
            retval = -ENOSPC;
            /*no windowspace in STP is available, native process should not call BT_write with no delay at all*/
            BT_ERR_FUNC("target packet length:%d, write success length:%d, retval = %d.\n", count, written, retval);
        }
        else
        {
            retval = written;
        }

    }else
    {
        retval = -EFAULT;
        BT_ERR_FUNC("target packet length:%d is not allowed, retval = %d.\n", count, retval);
    }

OUT:
    up(&wr_mtx);
    return (retval);
}
示例#8
0
ssize_t BT_write(struct file *filp, const char __user *buf, size_t count, loff_t *f_pos)
{
	INT32 retval = 0;
	INT32 write_size;
	INT32 written = 0;

	down(&wr_mtx);

	BT_DBG_FUNC("%s: count %zd pos %lld\n", __func__, count, *f_pos);
	if (rstflag) {
		if (rstflag == 1) {	/* Reset start */
			retval = -88;
			BT_INFO_FUNC("%s: detect whole chip reset start\n", __func__);
		} else if (rstflag == 2) {	/* Reset end */
			retval = -99;
			BT_INFO_FUNC("%s: detect whole chip reset end\n", __func__);
		}
		goto OUT;
	}

	if (count > 0) {
		if (count < BT_BUFFER_SIZE) {
			write_size = count;
		} else {
			write_size = BT_BUFFER_SIZE;
			BT_ERR_FUNC("%s: count > BT_BUFFER_SIZE\n", __func__);
		}

		if (copy_from_user(&o_buf[0], &buf[0], write_size)) {
			retval = -EFAULT;
			goto OUT;
		}

		written = mtk_wcn_stp_send_data(&o_buf[0], write_size, BT_TASK_INDX);
		if (0 == written) {
			retval = -ENOSPC;
			/* No space is available, native program should not call BT_write with no delay */
			BT_ERR_FUNC
			    ("Packet length %zd, sent length %d, retval = %d\n",
			     count, written, retval);
		} else {
			retval = written;
		}

	} else {
		retval = -EFAULT;
		BT_ERR_FUNC("Packet length %zd is not allowed, retval = %d\n", count, retval);
	}

OUT:
	up(&wr_mtx);
	return retval;
}
static int BT_open(struct inode *inode, struct file *file)
{
    BT_INFO_FUNC("%s: major %d minor %d (pid %d)\n", __func__,
        imajor(inode),
        iminor(inode),
        current->pid
        );

#if 1 /* GeorgeKuo: turn on function before check stp ready */
     /* turn on BT */
    if (MTK_WCN_BOOL_FALSE == mtk_wcn_wmt_func_on(WMTDRV_TYPE_BT)) {
        BT_WARN_FUNC("WMT turn on BT fail!\n");
        return -ENODEV;
    }else{
        retflag = 0;
        mtk_wcn_wmt_msgcb_reg(WMTDRV_TYPE_BT, bt_cdev_rst_cb);
        BT_INFO_FUNC("WMT register BT rst cb!\n");
    }
#endif

    if (mtk_wcn_stp_is_ready()) {
#if 0 /* GeorgeKuo: turn on function before check stp ready */
         /* turn on BT */
        if (MTK_WCN_BOOL_FALSE == mtk_wcn_wmt_func_on(WMTDRV_TYPE_BT)) {
            BT_WARN_FUNC("WMT turn on BT fail!\n");
            return -ENODEV;
        }
#endif
        mtk_wcn_stp_set_bluez(0);

        BT_INFO_FUNC("Now it's in MTK Bluetooth Mode\n");
        BT_INFO_FUNC("WMT turn on BT OK!\n");
        BT_INFO_FUNC("STP is ready!\n");
        platform_load_nvram_data(BT_NVRAM_CUSTOM_NAME,
            (char *)&g_nvram_btdata, sizeof(g_nvram_btdata));

        BT_INFO_FUNC("Read NVRAM : BD address %02x%02x%02x%02x%02x%02x Cap 0x%02x Codec 0x%02x\n",
            g_nvram_btdata[0], g_nvram_btdata[1], g_nvram_btdata[2],
            g_nvram_btdata[3], g_nvram_btdata[4], g_nvram_btdata[5],
            g_nvram_btdata[6], g_nvram_btdata[7]);

        mtk_wcn_stp_register_event_cb(BT_TASK_INDX, BT_event_cb);
		BT_INFO_FUNC("mtk_wcn_stp_register_event_cb finish\n");
    }
    else {
        BT_ERR_FUNC("STP is not ready\n");

        /*return error code*/
        return -ENODEV;
    }

//    init_MUTEX(&wr_mtx);
    sema_init(&wr_mtx, 1);
//    init_MUTEX(&rd_mtx);
    sema_init(&rd_mtx, 1);
	BT_INFO_FUNC("finish\n");

    return 0;
}
示例#10
0
INT32 platform_load_nvram_data(PINT8 filename, PINT8 buf, INT32 len)
{
	/* int ret; */
	BT_INFO_FUNC("platform_load_nvram_data ++ BDADDR\n");

	return nvram_read(filename, buf, len, 0);
}
int platform_load_nvram_data( char * filename, char * buf, int len)
{
    //int ret;
    BT_INFO_FUNC("platform_load_nvram_data ++ BDADDR\n");

    return nvram_read( filename, buf, len, 0);
}
示例#12
0
static int BT_init(void)
{
	dev_t dev = MKDEV(BT_major, 0);
	INT32 alloc_ret = 0;
	INT32 cdev_err = 0;
#if REMOVE_MK_NODE
	struct device *stpbt_dev = NULL;
#endif

	/*static allocate chrdev */
	alloc_ret = register_chrdev_region(dev, 1, BT_DRIVER_NAME);
	if (alloc_ret) {
		BT_ERR_FUNC("fail to register chrdev\n");
		return alloc_ret;
	}

	cdev_init(&BT_cdev, &BT_fops);
	BT_cdev.owner = THIS_MODULE;

	cdev_err = cdev_add(&BT_cdev, dev, BT_devs);
	if (cdev_err)
		goto error;
#if REMOVE_MK_NODE		/* mknod replace */

	stpbt_class = class_create(THIS_MODULE, "stpbt");
	if (IS_ERR(stpbt_class))
		goto error;
	stpbt_dev = device_create(stpbt_class, NULL, dev, NULL, "stpbt");
	if (IS_ERR(stpbt_dev))
		goto error;
#endif

	BT_INFO_FUNC("%s driver(major %d) installed.\n", BT_DRIVER_NAME, BT_major);
	retflag = 0;
	mtk_wcn_stp_register_event_cb(BT_TASK_INDX, NULL);

	/* init wait queue */
	init_waitqueue_head(&(inq));

	return 0;

error:

#if REMOVE_MK_NODE
	if (!IS_ERR(stpbt_dev))
		device_destroy(stpbt_class, dev);
	if (!IS_ERR(stpbt_class)) {
		class_destroy(stpbt_class);
		stpbt_class = NULL;
	}
#endif
	if (cdev_err == 0)
		cdev_del(&BT_cdev);

	if (alloc_ret == 0)
		unregister_chrdev_region(dev, BT_devs);

	return -1;
}
示例#13
0
static int BT_close(struct inode *inode, struct file *file)
{
	BT_INFO_FUNC("%s: major %d minor %d (pid %d)\n", __func__, imajor(inode), iminor(inode), current->pid);
	if (current->pid == 1)
		return 0;
	retflag = 0;
	mtk_wcn_wmt_msgcb_unreg(WMTDRV_TYPE_BT);
	mtk_wcn_stp_register_event_cb(BT_TASK_INDX, NULL);

	if (MTK_WCN_BOOL_FALSE == mtk_wcn_wmt_func_off(WMTDRV_TYPE_BT)) {
		BT_INFO_FUNC("WMT turn off BT fail!\n");
		return -EIO;	/* mostly, native programmer will not check this return value. */
	} else {
		BT_INFO_FUNC("WMT turn off BT OK!\n");
	}

	return 0;
}
示例#14
0
/* int BT_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg) */
long BT_unlocked_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
{
	INT32 retval = 0;
	MTK_WCN_BOOL bRet = MTK_WCN_BOOL_TRUE;
	ENUM_WMTHWVER_TYPE_T hw_ver_sym = WMTHWVER_INVALID;

	BT_DBG_FUNC("%s:  cmd: 0x%x\n", __func__, cmd);

	switch (cmd) {
	case COMBO_IOC_BT_HWVER:
		/* Get combo HW version */
		hw_ver_sym = mtk_wcn_wmt_hwver_get();
		BT_INFO_FUNC("%s: HW version = %d, sizeof(hw_ver_sym) = %zd\n",
			     __func__, hw_ver_sym, sizeof(hw_ver_sym));
		if (copy_to_user((int __user *)arg, &hw_ver_sym, sizeof(hw_ver_sym)))
			retval = -EFAULT;
		break;

	case COMBO_IOCTL_FW_ASSERT:
		/* Trigger FW assert for debug */
		BT_INFO_FUNC("%s: Host trigger FW assert......, reason:%lu\n", __func__, arg);
		bRet = mtk_wcn_wmt_assert(WMTDRV_TYPE_BT, arg);
		if (bRet == MTK_WCN_BOOL_TRUE) {
			BT_INFO_FUNC("Host trigger FW assert succeed\n");
			retval = 0;
		} else {
			BT_ERR_FUNC("Host trigger FW assert Failed\n");
			retval = (-EBUSY);
		}
		break;
	case COMBO_IOCTL_BT_IC_HW_VER:
		retval = mtk_wcn_wmt_ic_info_get(WMTCHIN_HWVER);
		break;
	case COMBO_IOCTL_BT_IC_FW_VER:
		retval = mtk_wcn_wmt_ic_info_get(WMTCHIN_FWVER);
		break;
	default:
		retval = -EFAULT;
		BT_ERR_FUNC("Unknown cmd (%d)\n", cmd);
		break;
	}

	return retval;
}
static void BT_exit(void)
{
    dev_t dev = MKDEV(BT_major, 0);
    retflag = 0;
    mtk_wcn_stp_register_event_cb(BT_TASK_INDX, NULL);  // unregister event callback function

    cdev_del(&BT_cdev);
    unregister_chrdev_region(dev, BT_devs);

    BT_INFO_FUNC("%s driver removed.\n", BT_DRIVER_NAME);
}
示例#16
0
static int BT_open(struct inode *inode, struct file *file)
{
	BT_INFO_FUNC("%s: major %d minor %d pid %d\n", __func__, imajor(inode), iminor(inode), current->pid);
	if (current->pid == 1)
		return 0;

	/* Turn on BT */
	if (MTK_WCN_BOOL_FALSE == mtk_wcn_wmt_func_on(WMTDRV_TYPE_BT)) {
		BT_WARN_FUNC("WMT turn on BT fail!\n");
		return -ENODEV;
	}

	BT_INFO_FUNC("WMT turn on BT OK!\n");
	rstflag = 0;

	if (mtk_wcn_stp_is_ready()) {

		mtk_wcn_stp_set_bluez(0);

		BT_INFO_FUNC("Now it's in MTK Bluetooth Mode\n");
		BT_INFO_FUNC("STP is ready!\n");

		BT_DBG_FUNC("Register BT event callback!\n");
		mtk_wcn_stp_register_event_cb(BT_TASK_INDX, BT_event_cb);
	} else {
		BT_ERR_FUNC("STP is not ready\n");
		mtk_wcn_wmt_func_off(WMTDRV_TYPE_BT);
		return -ENODEV;
	}

	BT_DBG_FUNC("Register BT reset callback!\n");
	mtk_wcn_wmt_msgcb_reg(WMTDRV_TYPE_BT, bt_cdev_rst_cb);

/* init_MUTEX(&wr_mtx); */
	sema_init(&wr_mtx, 1);
/* init_MUTEX(&rd_mtx); */
	sema_init(&rd_mtx, 1);
	BT_INFO_FUNC("%s: finish\n", __func__);

	return 0;
}
示例#17
0
static void BT_exit(void)
{
	dev_t dev = MKDEV(BT_major, 0);

#if REMOVE_MK_NODE
	device_destroy(stpbt_class, dev);
	class_destroy(stpbt_class);
	stpbt_class = NULL;
#endif

	cdev_del(&BT_cdev);
	unregister_chrdev_region(dev, BT_devs);

	BT_INFO_FUNC("%s driver removed\n", BT_DRIVER_NAME);
}
示例#18
0
static void BT_exit(void)
{
	dev_t dev = MKDEV(BT_major, 0);
	retflag = 0;
	mtk_wcn_stp_register_event_cb(BT_TASK_INDX, NULL);	/* unregister event callback function */
#if REMOVE_MK_NODE
	device_destroy(stpbt_class, dev);
	class_destroy(stpbt_class);
	stpbt_class = NULL;
#endif

	cdev_del(&BT_cdev);
	unregister_chrdev_region(dev, BT_devs);

	BT_INFO_FUNC("%s driver removed.\n", BT_DRIVER_NAME);
}
static void BT_exit(void)
{
    dev_t dev = MKDEV(BT_major, 0);
    retflag = 0;
    mtk_wcn_stp_register_event_cb(BT_TASK_INDX, NULL);  // unregister event callback function
#if WMT_CREATE_NODE_DYNAMIC
	if(bt_dev)
	{
		device_destroy(bt_class,dev);
		bt_dev = NULL;
	}
	if(bt_class)
	{
		class_destroy(bt_class);
		bt_class = NULL;
	}
#endif
    cdev_del(&BT_cdev);
    unregister_chrdev_region(dev, BT_devs);

    BT_INFO_FUNC("%s driver removed.\n", BT_DRIVER_NAME);
}
示例#20
0
static int BT_init(void)
{
	dev_t dev = MKDEV(BT_major, 0);
	int alloc_ret = 0;
	int cdev_err = 0;

/*static allocate chrdev*/
	alloc_ret = register_chrdev_region(dev, 1, BT_DRIVER_NAME);
	if (alloc_ret) {
		BT_ERR_FUNC("fail to register chrdev\n");
		return alloc_ret;
	}

	cdev_init(&BT_cdev, &BT_fops);
	BT_cdev.owner = THIS_MODULE;

	cdev_err = cdev_add(&BT_cdev, dev, BT_devs);
	if (cdev_err)
		goto error;

	BT_INFO_FUNC("%s driver(major %d) installed.\n",
		     BT_DRIVER_NAME, BT_major);
	retflag = 0;
	mtk_wcn_stp_register_event_cb(BT_TASK_INDX, NULL);

/* init wait queue */
	init_waitqueue_head(&(inq));

	return 0;

error:
	if (cdev_err == 0)
		cdev_del(&BT_cdev);

	if (alloc_ret == 0)
		unregister_chrdev_region(dev, BT_devs);

	return -1;
}
//int BT_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg)
long BT_unlocked_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
{
    int retval = 0;


    ENUM_WMTHWVER_TYPE_T hw_ver_sym = WMTHWVER_INVALID;
    BT_DBG_FUNC("BT_ioctl(): cmd (%d)\n", cmd);

    switch(cmd)
    {
#if 0
        case 0: // enable/disable STP
            /* George: STP is controlled by WMT only */
            /* mtk_wcn_stp_enable(arg); */
            break;
#endif
        case 1: // send raw data
            BT_DBG_FUNC("BT_ioctl(): disable raw data from BT dev \n");
            retval = -EINVAL;
            break;
        case COMBO_IOC_BT_HWVER:
            /*get combo hw version*/
            hw_ver_sym = mtk_wcn_wmt_hwver_get();

            BT_INFO_FUNC("BT_ioctl(): get hw version = %d, sizeof(hw_ver_sym) = %d\n", hw_ver_sym, sizeof(hw_ver_sym));
            if(copy_to_user((int __user *)arg, &hw_ver_sym, sizeof(hw_ver_sym))){
               retval = -EFAULT;
            }
            break;
        default:
            retval = -EFAULT;
            BT_DBG_FUNC("BT_ioctl(): unknown cmd (%d)\n", cmd);
            break;
    }

    return retval;
}