📄 kpp.c
字号:
}}static void kpp_timer_callback(unsigned long data){ if(kpp_timer_status !=0) mod_timer(&kpp_timer, jiffies + HZ/8000 + 2*HZ/100); kpp_scan_matrix();}static void kpp_isr(int irq, void *dev_id, struct pt_regs *regs){ //clear Key depress event _reg_KPP_KPSR |= KPP_KPKD_BIT_MASK; //clear key release event _reg_KPP_KPSR |= KPP_KPKR_BIT_MASK; //if first depress key if((kpp_timer_status == 0)&&(kpp_pressed == 0)) { //disable key depress interrupt _reg_KPP_KPSR &= ~KPP_KDIE_BIT_MASK; //enable key release interrupt _reg_KPP_KPSR |= KPP_KRIE_BIT_MASK; //Start timer spin_lock_irq(&kpp_lock); kpp_timer.expires = jiffies + HZ/8000 + 2*HZ/100; add_timer(&kpp_timer); kpp_timer_status = 1; spin_unlock_irq (&kpp_lock); return; } //if get key release interrupt else if((kpp_timer_status != 0)&&(kpp_pressed == 0)) { //release timer spin_lock_irq(&kpp_lock); kpp_timer_status = 0; del_timer(&kpp_timer); spin_unlock_irq(&kpp_lock); //disable key release interrupt _reg_KPP_KPSR &= ~KPP_KRIE_BIT_MASK; //enable key depress interrupt _reg_KPP_KPSR |= KPP_KDIE_BIT_MASK; return; }}/****************************************************************************** * Function Name: kpp_read * * Input: filp : the file * buf : data buffer * count : number of chars to be readed * l : offset of file * Value Returned: int : Return status.If no error, return 0. * * Description: read device driver * *****************************************************************************/ssize_t kpp_read(struct file * filp, char * buf, size_t count, loff_t * l){ key_code_t keycode; key_code_t * p_keycode; int nonBlocking; unsigned long flags; int ret = 0; nonBlocking = filp->f_flags & O_NONBLOCK; if( nonBlocking ) { if(!NODATA()) { save_flags(flags); cli(); p_keycode = get_data(); restore_flags(flags); keycode.low = p_keycode->low; keycode.high = p_keycode->high; keycode.status = p_keycode->status; __copy_to_user(buf, &keycode, sizeof(key_code_t)); TRACE("copy back \n"); ret = sizeof(key_code_t); return ret; } else return -EINVAL; } else { while(1) { if(!NODATA()) { save_flags(flags); cli(); p_keycode = get_data(); restore_flags(flags); keycode.low = p_keycode->low; keycode.high = p_keycode->high; keycode.status = p_keycode->status; __copy_to_user(buf, &keycode, sizeof(key_code_t)); TRACE("copy back \n"); ret = sizeof(key_code_t); return ret; } else { interruptible_sleep_on(&g_mx21_kpp_wait); if(signal_pending(current)) return -ERESTARTSYS; } } }}/****************************************************************************** * Function Name: kpp_release * * Input: inode : * filp : * Value Returned: int : Return status.If no error, return 0. * * Description: release resource when close the inode * *****************************************************************************/int kpp_release(struct inode * inode, struct file * filp){ printk("kpp_release: ----\n"); //disable the kpp interrupt mx2ads_mask_irq(KPP_IRQ); g_kpp_status &= ~KPP_OPEN_STATUS; MOD_DEC_USE_COUNT; return 0;}/****************************************************************************** * Function Name: kpp_open * * Input: inode : * filp : * Value Returned: int : Return status.If no error, return 0. * * Description: allocate resource when open the inode * *****************************************************************************/int kpp_open(struct inode * inode, struct file * filp){ printk("kpp_open: ----\n"); MOD_INC_USE_COUNT; //enable ADC interrupt kpp_hw_configure(); kpp_irq_enable(); g_kpp_status = KPP_OPEN_STATUS; return 0;}/****************************************************************************** * Function Name: kpp_fasync * * Input: fd : * filp : * mode : * Value Returned: int : Return status.If no error, return 0. * * Description: provide fasync functionality for select system call * *****************************************************************************/static int kpp_fasync(int fd, struct file *filp, int mode){ return 0;}/****************************************************************************** * Function Name: kpp_ioctl * * Input: inode : * filp : * cmd : command for ioctl * arg : parameter for command * Value Returned: int : Return status.If no error, return 0. * * Description: ioctl for this device driver * *****************************************************************************/int kpp_ioctl(struct inode * inode, struct file *filp, unsigned int cmd , unsigned long arg){ int ret = -EIO; int minor; return ret;}struct file_operations g_kpp_fops = { open: kpp_open, release: kpp_release, read: kpp_read, poll: NULL, ioctl: kpp_ioctl, fasync: kpp_fasync,}; int kpp_pm_handler(struct pm_dev *dev, pm_request_t rqst, void *data){ switch(rqst){ case PM_RESUME: if((g_kpp_status & KPP_SUSPEND_STATUS)!=0) { //enable clk _reg_CRM_PCCR1 |= 0x40000000; g_kpp_status &= ~KPP_SUSPEND_STATUS; } break; case PM_SUSPEND: if((g_kpp_status & KPP_OPEN_STATUS)!=0) { //disable clk _reg_CRM_PCCR1 &= ~0x40000000; g_kpp_status |= KPP_SUSPEND_STATUS; } break; default: break; } return 0;}/********************************************************kpp init function*Parameters:None*Return * 0 indicates SUCCESS* -1 indicates FAILURE*Description: ********************************************************/signed short __init kpp_init(void){ int tmp; g_mx21_kpp_buffer = 0;// printk("ok1 debug = %x mtd = %x \n",WAITQUEUE_DEBUG,CONFIG_MTD); init_timer(&kpp_timer); kpp_timer.function = kpp_timer_callback; g_kpp_major = devfs_register_chrdev(0, MODULE_NAME, &g_kpp_fops); if( g_kpp_major < 0 ) { TRACE("%s driver: Unable to register driver\n",MODULE_NAME); return -ENODEV; } g_devfs_handle = devfs_register(NULL, MODULE_NAME, DEVFS_FL_DEFAULT, g_kpp_major, 0, S_IFCHR | S_IRUSR | S_IWUSR, &g_kpp_fops, NULL); tmp = request_irq(KPP_IRQ, (void * )kpp_isr, SA_INTERRUPT|SA_SHIRQ, MODULE_NAME, MODULE_NAME); if(tmp) { printk("kpp_init:cannot init major= %d irq=%d\n", g_kpp_major, KPP_IRQ); devfs_unregister_chrdev(g_kpp_major, MODULE_NAME); devfs_unregister(g_devfs_handle); return -1; } if(-1 == init_buf()){ printk("kpp_init: cannot init kpp buffer, exit\n"); free_irq(KPP_IRQ,MODULE_NAME); devfs_unregister_chrdev(g_kpp_major, MODULE_NAME); devfs_unregister(g_devfs_handle); return -1; } init_waitqueue_head(&g_mx21_kpp_wait); g_kpp_pm = pm_register(PM_SYS_DEV, PM_SYS_VGA, kpp_pm_handler); g_kpp_status = 0; INFO("Kpp Driver 0.4.0\n"); INFO("Motorols SPS-Suzhou\n"); return 0;}void __exit kpp_cleanup(void){ /*Do some cleanup work*/ disable_irq(KPP_IRQ); free_irq(KPP_IRQ, MODULE_NAME); kfree(g_mx21_kpp_buffer); g_mx21_kpp_buffer = NULL; if(g_kpp_major>0) { devfs_unregister_chrdev(g_kpp_major, MODULE_NAME); devfs_unregister(g_devfs_handle); } pm_unregister(g_kpp_pm);}int init_module(void){ return kpp_init();}void cleanup_module(void){ kpp_cleanup();}MODULE_PARM(irq_mask, "i");MODULE_PARM(irq_list, "1-4i");MODULE_LICENSE("GPL");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -