📄 digi.c
字号:
buffer[wptr].pressure = flag; NEXTI(wptr); // goto next wptr}/****************************************************************************** * Function Name: get_block * * Input: block: size: * Value Returned: int : count of data size * * Description: read a block of 'touch' data from buffer, read count shall less * than size,but shall be as more as possible. the data shall not really copy * to upper layer,untill copy_to_user is invoked. *****************************************************************************///assume continuous bufferstatic int get_block(ts_event_t * * block, int size){ int cnt, rd; unsigned long flags; ts_event_t *p; if(NODATA()) return 0; cnt = 0; save_flags(flags); cli(); //critical section //get the actual size of data need read if(DSIZE()*sizeof(ts_event_t) >= size) { rd = size/sizeof(ts_event_t); } else { rd = DSIZE(); } * block = p = get_data(); cnt ++; while(p && (cnt < rd)) { if(rptr == 0) break; p = get_data(); cnt ++; } restore_flags(flags); return (cnt)*sizeof(ts_event_t); }/****************************************************************************** * Function Name: get_data * * Input: void : * Value Returned: ts_event_t : a 'touch' event data format * * Description: read a 'touch' event from data buffer * *****************************************************************************/// no really read out the data, so no copystatic ts_event_t* get_data(void){ ts_event_t *data; if(NODATA()) return NULL; data = & (buffer[rptr]); TRACE("*** Read - x: 0x%04x, y: 0x%04x, rptr: 0x%04x, wptr: 0x%04x\n", data->x, data->y, (int)rptr, (int)wptr); NEXTI(rptr); return data;}/****************************************************************************** * Function Name: digi_release * * Input: inode : * filp : * Value Returned: int : Return status.If no error, return 0. * * Description: release resource when close the inode * *****************************************************************************/int digi_release(struct inode * inode, struct file * filp){// printk("digi_release: ----\n"); digi_fasync(-1, filp, 0); //disable the ADC interrupt //disable_pen_interrupt(); touch_pan_disable_inter(); g_Digi_Status &= ~DIGI_OPEN_STATUS; MOD_DEC_USE_COUNT; return 0;}/****************************************************************************** * Function Name: digi_open * * Input: inode : * filp : * Value Returned: int : Return status.If no error, return 0. * * Description: allocate resource when open the inode * *****************************************************************************/int digi_open(struct inode * inode, struct file * filp){// printk("digi_open: ----\n"); MOD_INC_USE_COUNT; spi_flush_fifo(); //enable ADC interrupt touch_pan_disable_inter(); touch_pan_set_pos_inter();//set default polarity touch_pan_clear_inter(); touch_pan_enable_inter(); pen_timer_status = 0; g_Digi_Status = DIGI_OPEN_STATUS; return 0;}/****************************************************************************** * Function Name: digi_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 digi_fasync(int fd, struct file *filp, int mode){ /* TODO TODO put this data into file private data */ int minor = check_device( filp->f_dentry->d_inode); if ( minor == - 1) {// printk("<1>spi_fasyn:bad device minor\n"); return -ENODEV; } return( fasync_helper(fd, filp, mode, &ts_fasync) );}/****************************************************************************** * Function Name: digi_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 digi_ioctl(struct inode * inode, struct file *filp, unsigned int cmd , unsigned long arg){ int ret = -EIO; int minor; minor = check_device( inode ); if ( minor == - 1) { TRACE("bad minor\n"); return -ENODEV; } TRACE("minor=%08x cmd=%d\n",minor,cmd); return ret;}/****************************************************************************** * Function Name: spi_poll * * Input: filp : * wait : * Value Returned: int : Return status.If no error, return 0. * * Description: support poll and select * *****************************************************************************/unsigned int digi_poll(struct file * filp, struct poll_table_struct * wait){ int minor; minor = check_device( filp->f_dentry->d_inode); if ( minor == - 1) return -ENODEV; poll_wait(filp, &digi_wait, wait); return ( NODATA() ) ? 0 : (POLLIN | POLLRDNORM);}/****************************************************************************** * Function Name: digi_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 digi_read(struct file * filp, char * buf, size_t count, loff_t * l){ int nonBlocking = filp->f_flags & O_NONBLOCK; int minor; ts_event_t *ev; int cnt=0; minor = check_device( filp->f_dentry->d_inode ); if ( minor == - 1) return -ENODEV; if( nonBlocking ) { if( !NODATA() ) { /* returns length to be copied otherwise errno -Exxx */ cnt = get_block(&ev, count) ; if(cnt > count){ TRACE(KERN_ERR"Error read spi buffer\n"); return -EINVAL; } __copy_to_user(buf, (char*)ev, cnt ); return cnt; } else return -EINVAL; } else { /* check , when woken, there is a complete event to read */ while(1){ if( !NODATA() ) { cnt = get_block(&ev, count); if(cnt > count){ TRACE(KERN_ERR"Error read spi buffer\n"); return -EINVAL; } /* returns length to be copied otherwise errno -Exxx */ __copy_to_user(buf, (char*)ev, cnt); return cnt; } else { interruptible_sleep_on(&digi_wait); if(signal_pending(current)) return -ERESTARTSYS; } } }}/*** power management callback function, will disable the clk from PCCR0 register*/int digi_pm_handler(struct pm_dev *dev, pm_request_t rqst, void *data){ switch(rqst){ case PM_RESUME: if((g_Digi_Status & DIGI_SUSPEND_STATUS)!=0) { #ifdef CONFIG_ARCH_MX2ADS _reg_CRM_PCCR0 |= 0x00000010; #endif g_Digi_Status &= ~DIGI_SUSPEND_STATUS; } break; case PM_SUSPEND: if((g_Digi_Status & DIGI_OPEN_STATUS)!=0) { #ifdef CONFIG_ARCH_MX2ADS _reg_CRM_PCCR0 &= ~0x00000010; #endif g_Digi_Status |= DIGI_SUSPEND_STATUS; } break; default: break; } return 0;}/********************************************************digitizer init function*Parameters:None*Return * 0 indicates SUCCESS* -1 indicates FAILURE*Description: in this function should initialize the SPI device as well as the external touch pannel hardware********************************************************/signed short __init digi_init(void){ int tmp; int i; INFO("Pen Driver 0.4.0\n"); init_timer(&pen_timer); pen_timer.function = digi_sam_callback; tasklet_init(&digi_tasklet, digi_tasklet_action,(unsigned long)0); g_digi_major = devfs_register_chrdev(0, MODULE_NAME, &g_digi_fops); if ( g_digi_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_digi_major, 0, S_IFCHR | S_IRUSR | S_IWUSR, &g_digi_fops, NULL); /* g_proc_dir=create_proc_entry(MODULE_NAME, 0, NULL); g_proc_dir->read_proc=get_proc_list; g_proc_dir->data=NULL; */ tmp = request_irq(TPNL_IRQ, (void * )digi_isr, TPNL_INTR_MODE, MODULE_NAME, MODULE_NAME); if (tmp) { TRACE("digi_init:cannot init major= %d irq=%d\n", g_digi_major, TPNL_IRQ); devfs_unregister_chrdev(g_digi_major, MODULE_NAME); devfs_unregister(g_devfs_handle); return -1; } //init SPI buffer if(-1 == init_buf()){ TRACE("digi_init: cannot init spi buffer, exit\n"); free_irq(TPNL_IRQ,MODULE_NAME); devfs_unregister_chrdev(g_digi_major, MODULE_NAME); devfs_unregister(g_devfs_handle); disable_irq(TPNL_IRQ); return -1; } init_waitqueue_head(&digi_wait); //first init touch pannel touch_pan_set_inter();//set pen IRQ touch_pan_disable_inter();//mask pen interrupt //init pen touch pannel in GPIO,disabled //init SPI module spi_flush_fifo(); spi_init(); touch_pan_init(); touch_pan_enable();//enable touch pannel spi_exchange_data(0x90); spi_exchange_data(0x00); spi_exchange_data(0xD0); spi_exchange_data(0x00); spi_exchange_data(0x00); touch_pan_disable(); /* Delay for A/D Converter to be stable */ for(i=0;i<50000;i++); g_digi_pm = pm_register(PM_SYS_DEV, PM_SYS_VGA, digi_pm_handler); g_Digi_Status = 0; return 0;}void __exit digi_cleanup(void){ /*Do some cleanup work*/// disable_irq(TPNL_IRQ); free_irq(TPNL_IRQ, MODULE_NAME); tasklet_kill(&digi_tasklet); if(g_digi_major>0) { devfs_unregister_chrdev(g_digi_major, MODULE_NAME); devfs_unregister(g_devfs_handle); } pm_unregister(g_digi_pm);}int init_module(void){ digi_init(); return 0;}void cleanup_module(void){ digi_cleanup();}MODULE_PARM(irq_mask, "i");MODULE_PARM(irq_list, "1-4i");MODULE_LICENSE("GPL");//>>>>>Body
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -