📄 i2c-keypad.c
字号:
#include <linux/module.h>#include <linux/version.h>#include <linux/init.h>#include <linux/fs.h>#include <linux/delay.h>#include <linux/poll.h>#include <asm/uaccess.h> /* get_user,copy_to_user */#include <linux/string.h>#include <linux/kernel.h>#include <linux/sched.h>#include <linux/types.h>#include <linux/fcntl.h>#include <linux/interrupt.h>#include <linux/ptrace.h>#include <linux/ioport.h>#include <linux/in.h>//#include <linux/malloc.h>#include <linux/slab.h>#include <linux/vmalloc.h>#include <linux/string.h>#include <linux/init.h>#include <asm/bitops.h>#include <asm/io.h>#include <linux/errno.h>#include <linux/tqueue.h>#include <linux/wait.h>#include <asm/irq.h>#include <asm/arch/hardware.h>#include <asm/arch/irqs.h>//#include <linux/devfs_fs_kernel.h>#include <linux/miscdevice.h>//#include <asm/arch-mx1ads/hardware.h>#include "i2c-aa.h"#include <linux/i2c.h>#include <linux/i2c-algo-bit.h>#include <linux/i2c-id.h>#include "i2c-keypad.h"struct fasync_struct *keypadv_fasync;#define I2C_DRIVERID_KEYPAD 0x1003/* functions and interface */static int keypad_open(struct inode * inode, struct file * filp);static int keypad_release(struct inode * inode, struct file * filp);static int keypad_fasync(int fd, struct file *filp, int mode);static ssize_t keypad_read(struct file * , char * , size_t , loff_t * l);static ssize_t keypad_write(struct file *filp, const char *buf, size_t size, loff_t *l);static int keypad_ioctl(struct inode * inode, struct file *filp, unsigned int cmd , unsigned long arg);static unsigned int keypad_poll(struct file * filp, struct poll_table_struct * wait);static void keypad_interrupt(int , void *, struct pt_regs *); /* ISR :*/static int i2c_keypad_attach_adapter (struct i2c_adapter * adap);struct file_operations keypad_fops = { open: keypad_open, release: keypad_release, read: keypad_read, write: keypad_write, poll: keypad_poll, ioctl: keypad_ioctl, fasync: keypad_fasync,};static struct i2c_driver i2c_keypad_driver = { name: "i2c-keypad client driver", id: I2C_DRIVERID_KEYPAD, flags: I2C_DF_DUMMY | I2C_DF_NOTIFY, attach_adapter: i2c_keypad_attach_adapter, detach_client: NULL, command: NULL/* inc_use: NULL, dec_use: NULL, */};static struct i2c_client i2c_keypad_client = { name: "i2c-keypad client", id: 1, flags: 0, addr: -1, adapter: NULL, driver: &i2c_keypad_driver, data: NULL};/* local prototype */static int checkDevice(struct inode *pInode);int gMajor = 0;static struct keypad_struct keypadmx1;static int i2c_keypad_initialized = 0;wait_queue_head_t gkeypadWait;//static char interBuf[2];static char key[2];//static char bflag;/****************************************************************************** * Function Name: keypad_open * * Input: inode : * filp : * Value Returned: int : Return status.If no error, return 0. * * Description: allocate resource when open the inode * *****************************************************************************/int keypad_open(struct inode * inode, struct file * filp){ unsigned long flags,val; if(keypadmx1.gKeypadFlag == 1) return 1; save_flags_cli(flags); keypadmx1.gDataFlag = 0; keypadmx1.gKeypadFlag = 1; key[0] = 0; key[1] = 0; //bflag = PRESS_NO; restore_flags(flags); i2c_keypad_client.adapter->inc_use( i2c_keypad_client.adapter ); val = READREG(KEYPAD_IMR_B); val |= 0x00008000;//unmask the interrupt// val &= 0xFFFF7FFF;//mask the interrupt WRITEREG(KEYPAD_IMR_B,val); MOD_INC_USE_COUNT; return 0;}/****************************************************************************** * Function Name: keypad_release * * Input: inode : * filp : * Value Returned: int : Return status.If no error, return 0. * * Description: release resource when close the inode * *****************************************************************************/int keypad_release(struct inode * inode, struct file * filp){ unsigned long flags,val; save_flags_cli(flags); keypadmx1.gDataFlag = 0; keypadmx1.gKeypadFlag = 0; key[0] = 0; key[1] = 0; //bflag = PRESS_NO; restore_flags(flags); val = READREG(KEYPAD_IMR_B); val &= 0xFFFF7FFF;//mask the interrupt WRITEREG(KEYPAD_IMR_B,val); /* call the adapter's decrease usage count function */ i2c_keypad_client.adapter->dec_use( i2c_keypad_client.adapter ); MOD_DEC_USE_COUNT; return 0;}/*----------------------------------------------------------------------- * static SINT16 i2c_keypad_attach_adapter (struct i2c_adapter * adap) * This function is called when the associated driver is to install to the * I2C system. * It shall check whether it can handle the adapter. * * Parameter : * adap point o the adapter structure * Return : * Success 0 * Failure -1 *----------------------------------------------------------------------*/ static int i2c_keypad_attach_adapter (struct i2c_adapter * adap){ /* find out the adapter for the I2C module in the DBMX1*/ if (memcmp(adap->name, "DBMX1 I2C adapter", 17) != 0 ) return -ENODEV; /* store the adapter to the client driver */ i2c_keypad_client.adapter = adap; return 0;}/****************************************************************************** * Function Name: keypad_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 keypad_read(struct file * filp, char * buf, size_t count, loff_t * l){ char interBuf[2]; int nonBlocking; unsigned long flags; int ret = 0; nonBlocking = filp->f_flags & O_NONBLOCK; /*if((count % 3) != 0) return 0; */ if( nonBlocking ) { if( keypadmx1.gDataFlag == 1) { /*if(bflag == PRESS_DOWN) { interBuf[0] = PRESS_DOWN; } else if(bflag == PRESS_UP) { interBuf[0] = PRESS_UP; } else { interBuf[0] = PRESS_NO; } */ interBuf[0] = key[0]; interBuf[1] = key[1]; __copy_to_user(buf, interBuf, 2); save_flags_cli(flags); keypadmx1.gDataFlag = 0; restore_flags(flags); ret += 2; } else ret = 0; } else { while(1) { if( keypadmx1.gDataFlag == 1) { /*if(bflag == PRESS_DOWN) { interBuf[0] = PRESS_DOWN; } else if(bflag == PRESS_UP) { interBuf[0] = PRESS_UP; } else { interBuf[0] = PRESS_NO; } */ interBuf[0] = key[0]; interBuf[1] = key[1]; __copy_to_user(buf, interBuf, 2); save_flags_cli(flags); keypadmx1.gDataFlag = 0; restore_flags(flags); ret += 2; /*if((ret == count) || (ret > count)) break; */ break; } else { interruptible_sleep_on(&gkeypadWait); if(signal_pending(current)) break; } } }#ifdef TEST MX1_REG_PTD_DR &= ~0x80000000; printk("TOUT2 Falls\n");#endif return ret;}/****************************************************************************** * Function Name: keypad_write * * Input: filp : the file * buf : data buffer * count : number of chars to be written * l : offset of file * Value Returned: int : Return status.If no error, return 0. * * Description: read device driver * *****************************************************************************/static ssize_t keypad_write(struct file *filp, const char *buf, size_t size, loff_t *l){ struct i2c_msg msg; char wribuf[2]; if(!(size == 2)) return 0; __copy_from_user(wribuf,buf,size); msg.addr = i2c_keypad_client.addr; msg.flags = 0x00; msg.len = 2; msg.buf = wribuf; i2c_control( &i2c_keypad_client, I2C_IO_CHANGE_FREQ, 0x0F);//change to 400K freq i2c_transfer( i2c_keypad_client.adapter, &msg, 1 ); i2c_control( &i2c_keypad_client, I2C_IO_CHANGE_FREQ, DEFAULT_FREQ);//change back to 100K freq return size;}/****************************************************************************** * Function Name: keypad_fasync * * Input: fd : * filp :
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -