/***************************************************************************** * bt_hwctl_poll *****************************************************************************/ static unsigned int bt_hwctl_poll(struct file *file, poll_table *wait) { uint32_t mask = 0; eint_handle_method = 1; BT_HWCTL_DEBUG("bt_hwctl_poll eint_gen %d, eint_mask %d ++\n", eint_gen, eint_mask); //poll_wait(file, &eint_wait, wait); wait_event_interruptible(eint_wait, (eint_gen == 1 || eint_mask == 1)); BT_HWCTL_DEBUG("bt_hwctl_poll eint_gen %d, eint_mask %d --\n", eint_gen, eint_mask); if(mt6622_suspend_flag == 1) { printk("mt6622 wake lock 5000ms\n"); mt6622_suspend_flag = 0; wake_lock_timeout(&mt6622_irq_wakelock, msecs_to_jiffies(5000)); } if(eint_gen == 1){ mask = POLLIN|POLLRDNORM; eint_gen = 0; } else if (eint_mask == 1){ mask = POLLERR; eint_mask = 0; } return mask; }
/***************************************************************************** * bt_hwctl_release *****************************************************************************/ static int bt_hwctl_release(struct inode *inode, struct file *file) { BT_HWCTL_DEBUG("bt_hwctl_release\n"); eint_gen = 0; eint_mask = 0; return 0; }
static void __exit bt_hwctl_exit(void) { BT_HWCTL_DEBUG("bt_hwctl_exit\n"); platform_driver_unregister(&mt6622_driver); if (bh){ cdev_del(&bh->cdev); unregister_chrdev_region(bh->dev_t, 1); device_destroy(bh->cls, bh->dev_t); class_destroy(bh->cls); mutex_destroy(&bh->sem); kfree(bh); bh = NULL; } cancel_work_sync(&mtk_wcn_bt_event_work); destroy_workqueue(mtk_wcn_bt_workqueue); /* release gpio used by BT */ //mt_bt_gpio_release(); }
/***************************************************************************** * bt_hwctl_poll *****************************************************************************/ static unsigned int bt_hwctl_poll(struct file *file, poll_table *wait) { uint32_t mask = 0; BT_HWCTL_DEBUG("bt_hwctl_poll eint_gen %d, eint_mask %d ++\n", eint_gen, eint_mask); //poll_wait(file, &eint_wait, wait); wait_event_interruptible(eint_wait, (eint_gen == 1 || eint_mask == 1)); BT_HWCTL_DEBUG("bt_hwctl_poll eint_gen %d, eint_mask %d --\n", eint_gen, eint_mask); if(eint_gen == 1){ mask = POLLIN|POLLRDNORM; eint_gen = 0; } else if (eint_mask == 1){ mask = POLLERR; eint_mask = 0; } return mask; }
static void __exit bt_hwctl_exit(void) { BT_HWCTL_DEBUG("bt_hwctl_exit\n"); wake_lock_destroy(&mt6622_irq_wakelock); platform_driver_unregister(&mt6622_driver); if (bh){ cdev_del(&bh->cdev); unregister_chrdev_region(bh->dev_t, 1); device_destroy(bh->cls, bh->dev_t); class_destroy(bh->cls); mutex_destroy(&bh->sem); kfree(bh); bh = NULL; } /* release gpio used by BT */ //mt_bt_gpio_release(); }
static int __init bt_hwctl_init(void) { int ret = -1, err = -1; BT_HWCTL_DEBUG("bt_hwctl_init\n"); platform_driver_register(&mt6622_driver); if (!(bh = kzalloc(sizeof(struct bt_hwctl), GFP_KERNEL))) { BT_HWCTL_ALERT("bt_hwctl_init allocate dev struct failed\n"); err = -ENOMEM; goto ERR_EXIT; } ret = alloc_chrdev_region(&bh->dev_t, 0, 1, BTHWCTL_NAME); if (ret) { BT_HWCTL_ALERT("alloc chrdev region failed\n"); goto ERR_EXIT; } BT_HWCTL_DEBUG("alloc %s:%d:%d\n", BTHWCTL_NAME, MAJOR(bh->dev_t), MINOR(bh->dev_t)); cdev_init(&bh->cdev, &bt_hwctl_fops); bh->cdev.owner = THIS_MODULE; bh->cdev.ops = &bt_hwctl_fops; err = cdev_add(&bh->cdev, bh->dev_t, 1); if (err) { BT_HWCTL_ALERT("add chrdev failed\n"); goto ERR_EXIT; } bh->cls = class_create(THIS_MODULE, BTHWCTL_NAME); if (IS_ERR(bh->cls)) { err = PTR_ERR(bh->cls); BT_HWCTL_ALERT("class_create failed, errno:%d\n", err); goto ERR_EXIT; } bh->dev = device_create(bh->cls, NULL, bh->dev_t, NULL, BTHWCTL_NAME); mutex_init(&bh->sem); init_waitqueue_head(&eint_wait); /*INIT_WORK(&mtk_wcn_bt_event_work, mtk_wcn_bt_work_fun); mtk_wcn_bt_workqueue = create_singlethread_workqueue("mtk_wcn_bt"); if (!mtk_wcn_bt_workqueue) { printk("create_singlethread_workqueue failed.\n"); err = -ESRCH; goto ERR_EXIT; }*/ /* request gpio used by BT */ //mt_bt_gpio_init(); BT_HWCTL_DEBUG("bt_hwctl_init ok\n"); return 0; ERR_EXIT: if (err == 0) cdev_del(&bh->cdev); if (ret == 0) unregister_chrdev_region(bh->dev_t, 1); if (bh){ kfree(bh); bh = NULL; } return -1; }
/***************************************************************************** * bt_hwctl_ioctl *****************************************************************************/ static long bt_hwctl_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { int ret = 0; BT_HWCTL_DEBUG("bt_hwctl_ioctl\n"); if(!bh) { BT_HWCTL_ALERT("bt_hwctl struct not initialized\n"); return -EFAULT; } switch(cmd) { case BTHWCTL_IOCTL_SET_POWER: { unsigned long pwr = 0; if (copy_from_user(&pwr, (void*)arg, sizeof(unsigned long))) return -EFAULT; BT_HWCTL_DEBUG("BTHWCTL_IOCTL_SET_POWER: %d\n", (int)pwr); mutex_lock(&bh->sem); if (pwr){ ret = mt_bt_power_on(); } else{ mt_bt_power_off(); } mutex_unlock(&bh->sem); break; } case BTHWCTL_IOCTL_SET_EINT: { unsigned long eint = 0; if (copy_from_user(&eint, (void*)arg, sizeof(unsigned long))) return -EFAULT; BT_HWCTL_DEBUG("BTHWCTL_IOCTL_SET_EINT: %d\n", (int)eint); mutex_lock(&bh->sem); if (eint){ /* Enable irq from user space */ BT_HWCTL_DEBUG("Set BT EINT enable\n"); mt_bt_enable_irq(); } else{ /* Disable irq from user space, maybe time to close driver */ BT_HWCTL_DEBUG("Set BT EINT disable\n"); mt_bt_disable_irq(); eint_mask = 1; wake_up_interruptible(&eint_wait); } mutex_unlock(&bh->sem); break; } default: BT_HWCTL_ALERT("BTHWCTL_IOCTL not support\n"); return -EPERM; } return ret; }