/***************************************************************************** * 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_DBG("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_DBG("bt_hwctl_poll eint_gen %d, eint_mask %d --\n", eint_gen, eint_mask); if(mt6622_suspend_flag == 1 && eint_gen == 1) { printk("mt6622 wake lock 5000ms\n"); mt_bt_enable_irq(); 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; }
irqreturn_t mt_bt_eirq_handler(int i, void *arg) { struct hci_dev *hdev = NULL; //printk(KERN_ALERT "mt_bt_eirq_handler\n"); mt_bt_disable_irq(); if(eint_handle_method == 0) { //#ifdef CONFIG_BT_HCIUART /* BlueZ stack, hci_uart driver */ hdev = hci_dev_get(0); if(hdev == NULL){ /* Avoid the early interrupt before hci0 registered */ //BT_HWCTL_ALERT("hdev is NULL\n"); }else{ //BT_HWCTL_ALERT("EINT arrives! notify host wakeup\n"); printk("Send host wakeup command\n"); hci_send_cmd(hdev, 0xFCC1, 0, NULL); /* enable irq after receiving host wakeup command's event */ } mt_bt_enable_irq(); } else { //#else /* Maybe handle the interrupt in user space? */ eint_gen = 1; wake_up_interruptible(&eint_wait); /* Send host wakeup command in user space, enable irq then */ //#endif } return IRQ_HANDLED; }
/* Initialize device */ static int hci_uart_open(struct hci_dev *hdev) { BT_DBG("%s %p", hdev->name, hdev); /* Nothing to do for UART driver */ set_bit(HCI_RUNNING, &hdev->flags); #if defined(CONFIG_MT5931_MT6622) mt_bt_enable_irq(); #endif return 0; }
static void mtk_wcn_bt_work_fun(struct work_struct *work) { struct hci_dev *hdev = NULL; /* BlueZ stack, hci_uart driver */ hdev = hci_dev_get(0); if(hdev == NULL){ /* Avoid the early interrupt before hci0 registered */ //printk(KERN_ALERT "hdev is NULL\n "); }else{ //printk(KERN_ALERT "Send host wakeup command\n"); hci_send_cmd(hdev, 0xFCC1, 0, NULL); } mt_bt_enable_irq(); }
/***************************************************************************** * 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; }