1 #include <linux/init.h>
2 #include <linux/module.h>
3 #include <linux/types.h>
4 #include <linux/kernel.h>
6 #include <linux/cdev.h>
7 #include <linux/sched.h>
8 #include <asm/current.h>
9 #include <asm/uaccess.h>
10 #include <linux/fcntl.h>
11 #include <linux/poll.h>
12 #include <linux/time.h>
13 #include <linux/delay.h>
17 MODULE_LICENSE("Dual BSD/GPL");
19 #define BT_DRIVER_NAME "mtk_stp_BT_chrdev"
20 #define BT_DEV_MAJOR 192 // never used number
22 #define PFX "[MTK-BT] "
28 #define COMBO_IOC_BT_HWVER 6
30 #define COMBO_IOC_MAGIC 0xb0
31 #define COMBO_IOCTL_FW_ASSERT _IOWR(COMBO_IOC_MAGIC, 0, void*)
33 unsigned int gDbgLevel = BT_LOG_INFO;
35 #define BT_DBG_FUNC(fmt, arg...) if(gDbgLevel >= BT_LOG_DBG){ printk(PFX "%s: " fmt, __FUNCTION__ ,##arg);}
36 #define BT_INFO_FUNC(fmt, arg...) if(gDbgLevel >= BT_LOG_INFO){ printk(PFX "%s: " fmt, __FUNCTION__ ,##arg);}
37 #define BT_WARN_FUNC(fmt, arg...) if(gDbgLevel >= BT_LOG_WARN){ printk(PFX "%s: " fmt, __FUNCTION__ ,##arg);}
38 #define BT_ERR_FUNC(fmt, arg...) if(gDbgLevel >= BT_LOG_ERR){ printk(PFX "%s: " fmt, __FUNCTION__ ,##arg);}
39 #define BT_TRC_FUNC(f) if(gDbgLevel >= BT_LOG_DBG){printk(PFX "<%s> <%d>\n", __FUNCTION__, __LINE__);}
42 #define BT_NVRAM_CUSTOM_NAME "/data/BT_Addr"
44 static int BT_devs = 1; /* device count */
45 static int BT_major = BT_DEV_MAJOR; /* dynamic allocation */
46 module_param(BT_major, uint, 0);
47 static struct cdev BT_cdev;
49 static unsigned char i_buf[MTKSTP_BUFFER_SIZE]; // input buffer of read()
50 static unsigned char o_buf[MTKSTP_BUFFER_SIZE]; // output buffer of write()
51 static struct semaphore wr_mtx, rd_mtx;
52 static wait_queue_head_t inq; /* read queues */
53 static DECLARE_WAIT_QUEUE_HEAD(BT_wq);
55 volatile int retflag = 0;
57 unsigned char g_bt_bd_addr[10]={0x01,0x1a,0xfc,0x06,0x00,0x55,0x66,0x77,0x88,0x00};
58 unsigned char g_nvram_btdata[8];
60 static int nvram_read(char *filename, char *buf, ssize_t len, int offset)
66 mm_segment_t old_fs = get_fs();
69 fd = filp_open(filename, O_WRONLY|O_CREAT, 0644);
72 BT_ERR_FUNC("failed to open!!\n");
76 if ((fd->f_op == NULL) || (fd->f_op->read == NULL))
78 BT_ERR_FUNC("file can not be read!!\n");
82 if (fd->f_pos != offset) {
83 if (fd->f_op->llseek) {
84 if(fd->f_op->llseek(fd, offset, 0) != offset) {
85 BT_ERR_FUNC("[nvram_read] : failed to seek!!\n");
93 retLen = fd->f_op->read(fd,
100 filp_close(fd, NULL);
108 int platform_load_nvram_data( char * filename, char * buf, int len)
111 BT_INFO_FUNC("platform_load_nvram_data ++ BDADDR\n");
113 return nvram_read( filename, buf, len, 0);
116 static void bt_cdev_rst_cb(
117 ENUM_WMTDRV_TYPE_T src,
118 ENUM_WMTDRV_TYPE_T dst,
119 ENUM_WMTMSG_TYPE_T type,
124 To handle reset procedure please
126 ENUM_WMTRSTMSG_TYPE_T rst_msg;
128 BT_INFO_FUNC("sizeof(ENUM_WMTRSTMSG_TYPE_T) = %d\n", sizeof(ENUM_WMTRSTMSG_TYPE_T));
129 if(sz <= sizeof(ENUM_WMTRSTMSG_TYPE_T)){
130 memcpy((char *)&rst_msg, (char *)buf, sz);
131 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);
132 if((src == WMTDRV_TYPE_WMT) &&
133 (dst == WMTDRV_TYPE_BT) &&
134 (type == WMTMSG_TYPE_RESET)){
135 if(rst_msg == WMTRSTMSG_RESET_START){
136 BT_INFO_FUNC("BT restart start!\n");
138 wake_up_interruptible(&inq);
139 /*reset_start message handling*/
141 } else if(rst_msg == WMTRSTMSG_RESET_END){
142 BT_INFO_FUNC("BT restart end!\n");
144 wake_up_interruptible(&inq);
145 /*reset_end message handling*/
149 /*message format invalid*/
150 BT_INFO_FUNC("message format invalid!\n");
154 void BT_event_cb(void)
156 BT_DBG_FUNC("BT_event_cb() \n");
161 /* finally, awake any reader */
162 wake_up_interruptible(&inq); /* blocked in read() and select() */
167 unsigned int BT_poll(struct file *filp, poll_table *wait)
169 unsigned int mask = 0;
173 * The buffer is circular; it is considered full
174 * if "wp" is right behind "rp". "left" is 0 if the
175 * buffer is empty, and it is "1" if it is completely full.
177 if (mtk_wcn_stp_is_rxqueue_empty(BT_TASK_INDX))
179 poll_wait(filp, &inq, wait);
181 /* empty let select sleep */
182 if((!mtk_wcn_stp_is_rxqueue_empty(BT_TASK_INDX)) || retflag)
184 mask |= POLLIN | POLLRDNORM; /* readable */
189 mask |= POLLIN | POLLRDNORM; /* readable */
192 /* do we need condition? */
193 mask |= POLLOUT | POLLWRNORM; /* writable */
199 ssize_t BT_write(struct file *filp, const char __user *buf, size_t count, loff_t *f_pos)
205 BT_DBG_FUNC("%s: count %d pos %lld\n", __func__, count, *f_pos);
208 if (retflag == 1) //reset start
211 BT_INFO_FUNC("MT662x reset Write: start\n");
213 else if (retflag == 2) // reset end
216 BT_INFO_FUNC("MT662x reset Write: end\n");
223 int copy_size = (count < MTKSTP_BUFFER_SIZE) ? count : MTKSTP_BUFFER_SIZE;
224 if (copy_from_user(&o_buf[0], &buf[0], copy_size))
229 //printk("%02x ", val);
231 written = mtk_wcn_stp_send_data(&o_buf[0], copy_size, BT_TASK_INDX);
235 /*no windowspace in STP is available, native process should not call BT_write with no delay at all*/
236 BT_ERR_FUNC("target packet length:%d, write success length:%d, retval = %d.\n", count, written, retval);
246 BT_ERR_FUNC("target packet length:%d is not allowed, retval = %d.\n", count, retval);
254 ssize_t BT_read(struct file *filp, char __user *buf, size_t count, loff_t *f_pos)
260 BT_DBG_FUNC("BT_read(): count %d pos %lld\n", count, *f_pos);
263 if (retflag == 1) //reset start
266 BT_INFO_FUNC("MT662x reset Read: start\n");
268 else if (retflag == 2) // reset end
271 BT_INFO_FUNC("MT662x reset Read: end\n");
276 if(count > MTKSTP_BUFFER_SIZE)
278 count = MTKSTP_BUFFER_SIZE;
280 retval = mtk_wcn_stp_receive_data(i_buf, count, BT_TASK_INDX);
282 while(retval == 0) // got nothing, wait for STP's signal
284 /*If nonblocking mode, return directly O_NONBLOCK is specified during open() */
285 if (filp->f_flags & O_NONBLOCK){
286 BT_DBG_FUNC("Non-blocking BT_read() \n");
291 BT_DBG_FUNC("BT_read(): wait_event 1\n");
292 wait_event(BT_wq, flag != 0);
293 BT_DBG_FUNC("BT_read(): wait_event 2\n");
295 retval = mtk_wcn_stp_receive_data(i_buf, count, BT_TASK_INDX);
296 BT_DBG_FUNC("BT_read(): mtk_wcn_stp_receive_data() = %d\n", retval);
299 // we got something from STP driver
300 if (copy_to_user(buf, i_buf, retval))
308 BT_DBG_FUNC("BT_read(): retval = %d\n", retval);
312 //int BT_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg)
313 long BT_unlocked_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
316 MTK_WCN_BOOL bRet = MTK_WCN_BOOL_TRUE;
318 ENUM_WMTHWVER_TYPE_T hw_ver_sym = WMTHWVER_INVALID;
319 BT_DBG_FUNC("BT_ioctl(): cmd (%d)\n", cmd);
324 case 0: // enable/disable STP
325 /* George: STP is controlled by WMT only */
326 /* mtk_wcn_stp_enable(arg); */
329 case 1: // send raw data
330 BT_DBG_FUNC("BT_ioctl(): disable raw data from BT dev \n");
333 case COMBO_IOC_BT_HWVER:
334 /*get combo hw version*/
335 hw_ver_sym = mtk_wcn_wmt_hwver_get();
337 BT_INFO_FUNC("BT_ioctl(): get hw version = %d, sizeof(hw_ver_sym) = %d\n", hw_ver_sym, sizeof(hw_ver_sym));
338 if(copy_to_user((int __user *)arg, &hw_ver_sym, sizeof(hw_ver_sym))){
343 case COMBO_IOCTL_FW_ASSERT:
344 /* BT trigger fw assert for debug*/
345 BT_INFO_FUNC("BT Set fw assert......\n");
346 bRet = mtk_wcn_wmt_assert();
347 if (bRet == MTK_WCN_BOOL_TRUE) {
348 BT_INFO_FUNC("BT Set fw assert OK\n");
351 BT_INFO_FUNC("BT Set fw assert Failed\n");
358 BT_DBG_FUNC("BT_ioctl(): unknown cmd (%d)\n", cmd);
365 static int BT_open(struct inode *inode, struct file *file)
367 BT_INFO_FUNC("%s: major %d minor %d (pid %d)\n", __func__,
374 #if 1 /* GeorgeKuo: turn on function before check stp ready */
376 if (MTK_WCN_BOOL_FALSE == mtk_wcn_wmt_func_on(WMTDRV_TYPE_BT)) {
377 BT_WARN_FUNC("WMT turn on BT fail!\n");
381 mtk_wcn_wmt_msgcb_reg(WMTDRV_TYPE_BT, bt_cdev_rst_cb);
382 BT_INFO_FUNC("WMT register BT rst cb!\n");
386 if (mtk_wcn_stp_is_ready()) {
387 #if 0 /* GeorgeKuo: turn on function before check stp ready */
389 if (MTK_WCN_BOOL_FALSE == mtk_wcn_wmt_func_on(WMTDRV_TYPE_BT)) {
390 BT_WARN_FUNC("WMT turn on BT fail!\n");
394 mtk_wcn_stp_set_bluez(0);
396 BT_INFO_FUNC("Now it's in MTK Bluetooth Mode\n");
397 BT_INFO_FUNC("WMT turn on BT OK!\n");
398 BT_INFO_FUNC("STP is ready!\n");
399 platform_load_nvram_data(BT_NVRAM_CUSTOM_NAME,
400 (char *)&g_nvram_btdata, sizeof(g_nvram_btdata));
402 BT_INFO_FUNC("Read NVRAM : BD address %02x%02x%02x%02x%02x%02x Cap 0x%02x Codec 0x%02x\n",
403 g_nvram_btdata[0], g_nvram_btdata[1], g_nvram_btdata[2],
404 g_nvram_btdata[3], g_nvram_btdata[4], g_nvram_btdata[5],
405 g_nvram_btdata[6], g_nvram_btdata[7]);
407 mtk_wcn_stp_register_event_cb(BT_TASK_INDX, BT_event_cb);
408 BT_INFO_FUNC("mtk_wcn_stp_register_event_cb finish\n");
411 BT_ERR_FUNC("STP is not ready\n");
413 /*return error code*/
417 // init_MUTEX(&wr_mtx);
418 sema_init(&wr_mtx, 1);
419 // init_MUTEX(&rd_mtx);
420 sema_init(&rd_mtx, 1);
421 BT_INFO_FUNC("finish\n");
426 static int BT_close(struct inode *inode, struct file *file)
428 BT_INFO_FUNC("%s: major %d minor %d (pid %d)\n", __func__,
436 mtk_wcn_wmt_msgcb_unreg(WMTDRV_TYPE_BT);
437 mtk_wcn_stp_register_event_cb(BT_TASK_INDX, NULL);
439 if (MTK_WCN_BOOL_FALSE == mtk_wcn_wmt_func_off(WMTDRV_TYPE_BT)) {
440 BT_INFO_FUNC("WMT turn off BT fail!\n");
441 return -EIO; //mostly, native programmer will not check this return value.
444 BT_INFO_FUNC("WMT turn off BT OK!\n");
450 struct file_operations BT_fops = {
455 // .ioctl = BT_ioctl,
456 .unlocked_ioctl = BT_unlocked_ioctl,
460 static int BT_init(void)
462 dev_t dev = MKDEV(BT_major, 0);
466 /*static allocate chrdev*/
467 alloc_ret = register_chrdev_region(dev, 1, BT_DRIVER_NAME);
469 BT_ERR_FUNC("fail to register chrdev\n");
473 cdev_init(&BT_cdev, &BT_fops);
474 BT_cdev.owner = THIS_MODULE;
476 cdev_err = cdev_add(&BT_cdev, dev, BT_devs);
480 BT_INFO_FUNC("%s driver(major %d) installed.\n", BT_DRIVER_NAME, BT_major);
482 mtk_wcn_stp_register_event_cb(BT_TASK_INDX, NULL);
484 /* init wait queue */
485 init_waitqueue_head(&(inq));
494 unregister_chrdev_region(dev, BT_devs);
499 static void BT_exit(void)
501 dev_t dev = MKDEV(BT_major, 0);
503 mtk_wcn_stp_register_event_cb(BT_TASK_INDX, NULL); // unregister event callback function
506 unregister_chrdev_region(dev, BT_devs);
508 BT_INFO_FUNC("%s driver removed.\n", BT_DRIVER_NAME);
511 module_init(BT_init);
512 module_exit(BT_exit);