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"); } }
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"); } }
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); }
/* 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; }
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); }
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; }
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); }
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; }
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; }
/* 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); }
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; }
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); }
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); }
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; }