stp_chrdev_bt.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475
  1. #include <linux/init.h>
  2. #include <linux/module.h>
  3. #include <linux/types.h>
  4. #include <linux/kernel.h>
  5. #include <linux/fs.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>
  14. #include <linux/device.h>
  15. #include <linux/printk.h>
  16. #include "osal_typedef.h"
  17. #include "stp_exp.h"
  18. #include "wmt_exp.h"
  19. MODULE_LICENSE("Dual BSD/GPL");
  20. #define BT_DRIVER_NAME "mtk_stp_BT_chrdev"
  21. #define BT_DEV_MAJOR 192 /* Never used number */
  22. #define PFX "[MTK-BT] "
  23. #define BT_LOG_DBG 3
  24. #define BT_LOG_INFO 2
  25. #define BT_LOG_WARN 1
  26. #define BT_LOG_ERR 0
  27. #define COMBO_IOCTL_FW_ASSERT 2
  28. #define COMBO_IOCTL_BT_IC_HW_VER 3
  29. #define COMBO_IOCTL_BT_IC_FW_VER 4
  30. #define COMBO_IOC_BT_HWVER 5
  31. static UINT32 gDbgLevel = BT_LOG_INFO;
  32. #define BT_DBG_FUNC(fmt, arg...) \
  33. do { if (gDbgLevel >= BT_LOG_DBG) \
  34. pr_debug(PFX "%s: " fmt, __func__ , ##arg); \
  35. } while (0)
  36. #define BT_INFO_FUNC(fmt, arg...) \
  37. do { if (gDbgLevel >= BT_LOG_INFO) \
  38. pr_warn(PFX "%s: " fmt, __func__ , ##arg); \
  39. } while (0)
  40. #define BT_WARN_FUNC(fmt, arg...) \
  41. do { if (gDbgLevel >= BT_LOG_WARN) \
  42. pr_err(PFX "%s: " fmt, __func__ , ##arg); \
  43. } while (0)
  44. #define BT_ERR_FUNC(fmt, arg...) \
  45. do { if (gDbgLevel >= BT_LOG_ERR) \
  46. pr_err(PFX "%s: " fmt, __func__ , ##arg); \
  47. } while (0)
  48. #define VERSION "1.0"
  49. static INT32 BT_devs = 1; /* Device count */
  50. static INT32 BT_major = BT_DEV_MAJOR; /* Dynamic allocation */
  51. module_param(BT_major, uint, 0);
  52. static struct cdev BT_cdev;
  53. #define BT_BUFFER_SIZE 2048
  54. static UINT8 i_buf[BT_BUFFER_SIZE]; /* Input buffer of read() */
  55. static UINT8 o_buf[BT_BUFFER_SIZE]; /* Output buffer of write() */
  56. static struct semaphore wr_mtx, rd_mtx;
  57. /* Wait queue for poll and read */
  58. static wait_queue_head_t inq;
  59. static DECLARE_WAIT_QUEUE_HEAD(BT_wq);
  60. static INT32 flag;
  61. /* Reset flag for whole chip reset senario */
  62. static volatile INT32 rstflag;
  63. static VOID bt_cdev_rst_cb(ENUM_WMTDRV_TYPE_T src,
  64. ENUM_WMTDRV_TYPE_T dst, ENUM_WMTMSG_TYPE_T type, PVOID buf, UINT32 sz)
  65. {
  66. /*
  67. Handle whole chip reset messages
  68. */
  69. ENUM_WMTRSTMSG_TYPE_T rst_msg;
  70. if (sz <= sizeof(ENUM_WMTRSTMSG_TYPE_T)) {
  71. memcpy((PINT8)&rst_msg, (PINT8)buf, sz);
  72. BT_DBG_FUNC("src = %d, dst = %d, type = %d, buf = 0x%x sz = %d, max = %d\n", src,
  73. dst, type, rst_msg, sz, WMTRSTMSG_RESET_MAX);
  74. if ((src == WMTDRV_TYPE_WMT) && (dst == WMTDRV_TYPE_BT)
  75. && (type == WMTMSG_TYPE_RESET)) {
  76. if (rst_msg == WMTRSTMSG_RESET_START) {
  77. BT_INFO_FUNC("BT reset start!\n");
  78. rstflag = 1;
  79. wake_up_interruptible(&inq);
  80. } else if (rst_msg == WMTRSTMSG_RESET_END) {
  81. BT_INFO_FUNC("BT reset end!\n");
  82. rstflag = 2;
  83. wake_up_interruptible(&inq);
  84. }
  85. }
  86. } else {
  87. /* Invalid message format */
  88. BT_WARN_FUNC("Invalid message format!\n");
  89. }
  90. }
  91. VOID BT_event_cb(VOID)
  92. {
  93. BT_DBG_FUNC("BT_event_cb()\n");
  94. flag = 1;
  95. /*
  96. * Finally, wake up any reader blocked in poll or read
  97. */
  98. wake_up_interruptible(&inq);
  99. wake_up(&BT_wq);
  100. }
  101. unsigned int BT_poll(struct file *filp, poll_table *wait)
  102. {
  103. UINT32 mask = 0;
  104. /* down(&wr_mtx); */
  105. if (mtk_wcn_stp_is_rxqueue_empty(BT_TASK_INDX)) {
  106. poll_wait(filp, &inq, wait);
  107. if (!mtk_wcn_stp_is_rxqueue_empty(BT_TASK_INDX) || rstflag)
  108. /* BT Rx queue has valid data, or whole chip reset occurs */
  109. mask |= POLLIN | POLLRDNORM; /* Readable */
  110. } else {
  111. mask |= POLLIN | POLLRDNORM; /* Readable */
  112. }
  113. /* Do we need condition here? */
  114. mask |= POLLOUT | POLLWRNORM; /* Writable */
  115. /* up(&wr_mtx); */
  116. return mask;
  117. }
  118. ssize_t BT_write(struct file *filp, const char __user *buf, size_t count, loff_t *f_pos)
  119. {
  120. INT32 retval = 0;
  121. INT32 write_size;
  122. INT32 written = 0;
  123. down(&wr_mtx);
  124. BT_DBG_FUNC("%s: count %zd pos %lld\n", __func__, count, *f_pos);
  125. if (rstflag) {
  126. if (rstflag == 1) { /* Reset start */
  127. retval = -88;
  128. BT_INFO_FUNC("%s: detect whole chip reset start\n", __func__);
  129. } else if (rstflag == 2) { /* Reset end */
  130. retval = -99;
  131. BT_INFO_FUNC("%s: detect whole chip reset end\n", __func__);
  132. }
  133. goto OUT;
  134. }
  135. if (count > 0) {
  136. if (count < BT_BUFFER_SIZE) {
  137. write_size = count;
  138. } else {
  139. write_size = BT_BUFFER_SIZE;
  140. BT_ERR_FUNC("%s: count > BT_BUFFER_SIZE\n", __func__);
  141. }
  142. if (copy_from_user(&o_buf[0], &buf[0], write_size)) {
  143. retval = -EFAULT;
  144. goto OUT;
  145. }
  146. written = mtk_wcn_stp_send_data(&o_buf[0], write_size, BT_TASK_INDX);
  147. if (0 == written) {
  148. retval = -ENOSPC;
  149. /* No space is available, native program should not call BT_write with no delay */
  150. BT_ERR_FUNC
  151. ("Packet length %zd, sent length %d, retval = %d\n",
  152. count, written, retval);
  153. } else {
  154. retval = written;
  155. }
  156. } else {
  157. retval = -EFAULT;
  158. BT_ERR_FUNC("Packet length %zd is not allowed, retval = %d\n", count, retval);
  159. }
  160. OUT:
  161. up(&wr_mtx);
  162. return retval;
  163. }
  164. ssize_t BT_read(struct file *filp, char __user *buf, size_t count, loff_t *f_pos)
  165. {
  166. static int chip_reset_count;
  167. INT32 retval = 0;
  168. down(&rd_mtx);
  169. BT_DBG_FUNC("%s: count %zd pos %lld\n", __func__, count, *f_pos);
  170. if (rstflag) {
  171. if (rstflag == 1) { /* Reset start */
  172. retval = -88;
  173. if ((chip_reset_count%500) == 0)
  174. BT_INFO_FUNC("%s: detect whole chip reset start, %d\n", __func__, chip_reset_count);
  175. chip_reset_count++;
  176. } else if (rstflag == 2) { /* Reset end */
  177. retval = -99;
  178. BT_INFO_FUNC("%s: detect whole chip reset end\n", __func__);
  179. chip_reset_count = 0;
  180. }
  181. goto OUT;
  182. }
  183. if (count > BT_BUFFER_SIZE) {
  184. count = BT_BUFFER_SIZE;
  185. BT_ERR_FUNC("%s: count > BT_BUFFER_SIZE\n", __func__);
  186. }
  187. retval = mtk_wcn_stp_receive_data(i_buf, count, BT_TASK_INDX);
  188. while (retval == 0) { /* Got nothing, wait for STP's signal */
  189. /*
  190. * If nonblocking mode, return directly.
  191. * O_NONBLOCK is specified during open()
  192. */
  193. if (filp->f_flags & O_NONBLOCK) {
  194. BT_DBG_FUNC("Non-blocking BT_read\n");
  195. retval = -EAGAIN;
  196. goto OUT;
  197. }
  198. BT_DBG_FUNC("%s: wait_event 1\n", __func__);
  199. wait_event(BT_wq, flag != 0);
  200. BT_DBG_FUNC("%s: wait_event 2\n", __func__);
  201. flag = 0;
  202. retval = mtk_wcn_stp_receive_data(i_buf, count, BT_TASK_INDX);
  203. BT_DBG_FUNC("%s: mtk_wcn_stp_receive_data returns %d\n", __func__, retval);
  204. }
  205. /* Got something from STP driver */
  206. if (copy_to_user(buf, i_buf, retval)) {
  207. retval = -EFAULT;
  208. goto OUT;
  209. }
  210. OUT:
  211. up(&rd_mtx);
  212. BT_DBG_FUNC("%s: retval = %d\n", __func__, retval);
  213. return retval;
  214. }
  215. /* int BT_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg) */
  216. long BT_unlocked_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
  217. {
  218. INT32 retval = 0;
  219. MTK_WCN_BOOL bRet = MTK_WCN_BOOL_TRUE;
  220. ENUM_WMTHWVER_TYPE_T hw_ver_sym = WMTHWVER_INVALID;
  221. BT_DBG_FUNC("%s: cmd: 0x%x\n", __func__, cmd);
  222. switch (cmd) {
  223. case COMBO_IOC_BT_HWVER:
  224. /* Get combo HW version */
  225. hw_ver_sym = mtk_wcn_wmt_hwver_get();
  226. BT_INFO_FUNC("%s: HW version = %d, sizeof(hw_ver_sym) = %zd\n",
  227. __func__, hw_ver_sym, sizeof(hw_ver_sym));
  228. if (copy_to_user((int __user *)arg, &hw_ver_sym, sizeof(hw_ver_sym)))
  229. retval = -EFAULT;
  230. break;
  231. case COMBO_IOCTL_FW_ASSERT:
  232. /* Trigger FW assert for debug */
  233. BT_INFO_FUNC("%s: Host trigger FW assert......, reason:%lu\n", __func__, arg);
  234. bRet = mtk_wcn_wmt_assert(WMTDRV_TYPE_BT, arg);
  235. if (bRet == MTK_WCN_BOOL_TRUE) {
  236. BT_INFO_FUNC("Host trigger FW assert succeed\n");
  237. retval = 0;
  238. } else {
  239. BT_ERR_FUNC("Host trigger FW assert Failed\n");
  240. retval = (-EBUSY);
  241. }
  242. break;
  243. case COMBO_IOCTL_BT_IC_HW_VER:
  244. retval = mtk_wcn_wmt_ic_info_get(WMTCHIN_HWVER);
  245. break;
  246. case COMBO_IOCTL_BT_IC_FW_VER:
  247. retval = mtk_wcn_wmt_ic_info_get(WMTCHIN_FWVER);
  248. break;
  249. default:
  250. retval = -EFAULT;
  251. BT_ERR_FUNC("Unknown cmd (%d)\n", cmd);
  252. break;
  253. }
  254. return retval;
  255. }
  256. long BT_compat_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
  257. {
  258. return BT_unlocked_ioctl(filp, cmd, arg);
  259. }
  260. static int BT_open(struct inode *inode, struct file *file)
  261. {
  262. BT_INFO_FUNC("%s: major %d minor %d pid %d\n", __func__, imajor(inode), iminor(inode), current->pid);
  263. if (current->pid == 1)
  264. return 0;
  265. /* Turn on BT */
  266. if (MTK_WCN_BOOL_FALSE == mtk_wcn_wmt_func_on(WMTDRV_TYPE_BT)) {
  267. BT_WARN_FUNC("WMT turn on BT fail!\n");
  268. return -ENODEV;
  269. }
  270. BT_INFO_FUNC("WMT turn on BT OK!\n");
  271. rstflag = 0;
  272. if (mtk_wcn_stp_is_ready()) {
  273. mtk_wcn_stp_set_bluez(0);
  274. BT_INFO_FUNC("Now it's in MTK Bluetooth Mode\n");
  275. BT_INFO_FUNC("STP is ready!\n");
  276. BT_DBG_FUNC("Register BT event callback!\n");
  277. mtk_wcn_stp_register_event_cb(BT_TASK_INDX, BT_event_cb);
  278. } else {
  279. BT_ERR_FUNC("STP is not ready\n");
  280. mtk_wcn_wmt_func_off(WMTDRV_TYPE_BT);
  281. return -ENODEV;
  282. }
  283. BT_DBG_FUNC("Register BT reset callback!\n");
  284. mtk_wcn_wmt_msgcb_reg(WMTDRV_TYPE_BT, bt_cdev_rst_cb);
  285. /* init_MUTEX(&wr_mtx); */
  286. sema_init(&wr_mtx, 1);
  287. /* init_MUTEX(&rd_mtx); */
  288. sema_init(&rd_mtx, 1);
  289. BT_INFO_FUNC("%s: finish\n", __func__);
  290. return 0;
  291. }
  292. static int BT_close(struct inode *inode, struct file *file)
  293. {
  294. BT_INFO_FUNC("%s: major %d minor %d pid %d\n", __func__, imajor(inode), iminor(inode), current->pid);
  295. if (current->pid == 1)
  296. return 0;
  297. rstflag = 0;
  298. mtk_wcn_wmt_msgcb_unreg(WMTDRV_TYPE_BT);
  299. mtk_wcn_stp_register_event_cb(BT_TASK_INDX, NULL);
  300. if (MTK_WCN_BOOL_FALSE == mtk_wcn_wmt_func_off(WMTDRV_TYPE_BT)) {
  301. BT_ERR_FUNC("WMT turn off BT fail!\n");
  302. return -EIO; /* Mostly, native program will not check this return value. */
  303. }
  304. BT_INFO_FUNC("WMT turn off BT OK!\n");
  305. return 0;
  306. }
  307. const struct file_operations BT_fops = {
  308. .open = BT_open,
  309. .release = BT_close,
  310. .read = BT_read,
  311. .write = BT_write,
  312. /* .ioctl = BT_ioctl, */
  313. .unlocked_ioctl = BT_unlocked_ioctl,
  314. .compat_ioctl = BT_compat_ioctl,
  315. .poll = BT_poll
  316. };
  317. #if REMOVE_MK_NODE
  318. struct class *stpbt_class = NULL;
  319. #endif
  320. static int BT_init(void)
  321. {
  322. dev_t dev = MKDEV(BT_major, 0);
  323. INT32 alloc_ret = 0;
  324. INT32 cdev_err = 0;
  325. #if REMOVE_MK_NODE
  326. struct device *stpbt_dev = NULL;
  327. #endif
  328. /* Static allocate char device */
  329. alloc_ret = register_chrdev_region(dev, 1, BT_DRIVER_NAME);
  330. if (alloc_ret) {
  331. BT_ERR_FUNC("%s: Failed to register char device\n", __func__);
  332. return alloc_ret;
  333. }
  334. cdev_init(&BT_cdev, &BT_fops);
  335. BT_cdev.owner = THIS_MODULE;
  336. cdev_err = cdev_add(&BT_cdev, dev, BT_devs);
  337. if (cdev_err)
  338. goto error;
  339. #if REMOVE_MK_NODE
  340. stpbt_class = class_create(THIS_MODULE, "stpbt");
  341. if (IS_ERR(stpbt_class))
  342. goto error;
  343. stpbt_dev = device_create(stpbt_class, NULL, dev, NULL, "stpbt");
  344. if (IS_ERR(stpbt_dev))
  345. goto error;
  346. #endif
  347. BT_INFO_FUNC("%s driver(major %d) installed\n", BT_DRIVER_NAME, BT_major);
  348. /* Init wait queue */
  349. init_waitqueue_head(&(inq));
  350. return 0;
  351. error:
  352. #if REMOVE_MK_NODE
  353. if (!IS_ERR(stpbt_dev))
  354. device_destroy(stpbt_class, dev);
  355. if (!IS_ERR(stpbt_class)) {
  356. class_destroy(stpbt_class);
  357. stpbt_class = NULL;
  358. }
  359. #endif
  360. if (cdev_err == 0)
  361. cdev_del(&BT_cdev);
  362. if (alloc_ret == 0)
  363. unregister_chrdev_region(dev, BT_devs);
  364. return -1;
  365. }
  366. static void BT_exit(void)
  367. {
  368. dev_t dev = MKDEV(BT_major, 0);
  369. #if REMOVE_MK_NODE
  370. device_destroy(stpbt_class, dev);
  371. class_destroy(stpbt_class);
  372. stpbt_class = NULL;
  373. #endif
  374. cdev_del(&BT_cdev);
  375. unregister_chrdev_region(dev, BT_devs);
  376. BT_INFO_FUNC("%s driver removed\n", BT_DRIVER_NAME);
  377. }
  378. #ifdef MTK_WCN_REMOVE_KERNEL_MODULE
  379. int mtk_wcn_stpbt_drv_init(void)
  380. {
  381. return BT_init();
  382. }
  383. EXPORT_SYMBOL(mtk_wcn_stpbt_drv_init);
  384. void mtk_wcn_stpbt_drv_exit(void)
  385. {
  386. return BT_exit();
  387. }
  388. EXPORT_SYMBOL(mtk_wcn_stpbt_drv_exit);
  389. #else
  390. module_init(BT_init);
  391. module_exit(BT_exit);
  392. #endif