//**************************************************************** // Button-ts.c // 2011-11-25 // Light //**************************************************************** #include <linux/module.h> #include <linux/init.h> #include <linux/fs.h> #include <linux/interrupt.h> #include <linux/irq.h> #include <linux/sched.h> #include <linux/pm.h> #include <linux/sysctl.h> #include <linux/proc_fs.h> #include <linux/delay.h> #include <linux/platform_device.h> #include <linux/input.h> #include <linux/gpio_keys.h> #include <mach/gpio.h> #include <plat/gpio-cfg.h> #include <mach/regs-gpio.h> #include <linux/i2c.h> //================================================================================================== #include <linux/init.h> #include <linux/module.h> #include <linux/kernel.h> #include <linux/fs.h> #include <linux/delay.h> #include <linux/slab.h> #include <linux/irq.h> #include <linux/poll.h> #include <linux/delay.h> #include <linux/device.h> #include <linux/gpio.h> #include <mach/regs-gpio.h> #include <mach/hardware.h> #include <asm/irq.h> #include <asm/io.h> #define IIC_DEVICE_ADDRESS 0x33 #define SCL_H { gpio_set_value (S5PV210_GPG3(5), 1) ; } #define SCL_L { gpio_set_value (S5PV210_GPG3(5), 0) ; } #define SDA_H { gpio_set_value (S5PV210_GPG3(6), 1) ; } #define SDA_L { gpio_set_value (S5PV210_GPG3(6), 0) ; } #define SDA_IN { gpio_direction_input (S5PV210_GPG3(6)); } #define SDA_OUT { gpio_direction_output (S5PV210_GPG3(6),1); } #define WHILE_SDA_HIGH (gpio_get_value (S5PV210_GPG3(6))) unsigned int ByteDelayTimeout = 0x0700; unsigned int BitDelayTimeout = 0x200; //unsigned int BitDelayTimeout = 0x1000; static void ByteDelay( void ); static void BitDelay ( void ); static int dvcIIC_read ( char *, size_t ); static int dvcIIC_write ( char *, size_t ); static void InterfaceInit ( void ); static void I2C_Start ( void ); static void I2C_Stop ( void ); static void I2C_Ack ( void ); static void I2C_Nack ( void ); //-------------------------------------------------------------------------------------------------- static void I2C_Start(void) { SDA_OUT ; SDA_H ; BitDelay () ; SCL_H ; BitDelay () ; SDA_L ; BitDelay () ; } static void I2C_Stop(void) { SDA_OUT ; SDA_L ; BitDelay () ; SCL_H ; BitDelay () ; SDA_H ; BitDelay () ; } static void I2C_Ack(void) { SDA_OUT ; SDA_L ; BitDelay () ; SCL_H ; BitDelay () ; SCL_L ; BitDelay () ; SDA_IN ; BitDelay () ; } static void I2C_Ack1(void) { int i=0; SCL_H ; BitDelay () ; SDA_IN ; while((WHILE_SDA_HIGH)&&(i<255)) i++; //无应答延时一段时间后默认已经收到 SCL_L ; BitDelay () ; SDA_OUT; BitDelay () ; } static void I2C_Nack(void) { SDA_OUT ; SDA_H ; BitDelay () ; SCL_H ; BitDelay () ; SCL_L ; BitDelay () ; SCL_H ; } //-------------------------------------------------------------------------------------------------- static char Write_I2C_Byte ( char byte ) { char i; SCL_L; BitDelay (); for(i = 0 ; i < 8 ; i++) { if((byte & 0x80) == 0x80) {SDA_H;} else {SDA_L;} BitDelay () ; SCL_H ; BitDelay () ; SCL_L ; BitDelay () ; byte <<= 1 ; } return 1 ; } //-------------------------------------------------------------------------------------------------- static char Read_I2C_Byte ( void ) { char i, buff = 0 ; SCL_L ; BitDelay () ; for(i = 0 ; i < 8 ; i++) { SDA_OUT; SDA_H ; BitDelay () ; SCL_H ; SDA_IN ; BitDelay () ; if(WHILE_SDA_HIGH) buff |= 0x01 ; else buff &=~0x01; if(i<7) buff <<= 1 ; SCL_L ; BitDelay () ; } return buff ; } //-------------------------------------------------------------------------------------------------- static void ByteDelay ( void ) { volatile unsigned int dwTimeout ; dwTimeout = ByteDelayTimeout ; while ( --dwTimeout ) { asm ( "nop" ) ; } } static void BitDelay ( void ) { volatile unsigned int dwTimeout ; dwTimeout = BitDelayTimeout ; while ( --dwTimeout ) { asm ( "nop" ) ; } } //-------------------------------------------------------------------------------------------------- static void InterfaceInit ( void ) { gpio_direction_output (S5PV210_GPG3(5), 1); // SCL OUT gpio_direction_output (S5PV210_GPG3(6), 1); // SDA OUT gpio_set_value (S5PV210_GPG3(5), 1); gpio_set_value (S5PV210_GPG3(6), 1); ByteDelay () ; ByteDelay () ; ByteDelay () ; } //-------------------------------------------------------------------------------------------------- //-------------------------------------------------------------------------------------------------- static int dvcIIC_read ( char *data, size_t count) { int i; I2C_Start () ; Write_I2C_Byte((IIC_DEVICE_ADDRESS<<1)+1); I2C_Ack1() ; for ( i = 0; i < count; i++ ) { data[i] = Read_I2C_Byte (); I2C_Ack () ; //printk( "0x%x ", data[i] ); } Read_I2C_Byte () ; I2C_Nack () ; I2C_Stop () ; return 0; } //-------------------------------------------------------------------------------------------------- static int dvcIIC_write ( char *data, size_t size) { int i; I2C_Start () ; Write_I2C_Byte ((IIC_DEVICE_ADDRESS<<1)); I2C_Ack1 () ; for( i = 0; i < size; i++ ) { //printk( "0x%x ", data[i] ); Write_I2C_Byte ( data[i] ); I2C_Ack1 (); } I2C_Stop (); I2C_Nack (); I2C_Stop (); return 0; } //-------------------------------------------------------------------------------------------------- //------------------------------------------------------------------------------------------------- void delay() { unsigned int i,j; for(i=5000;i>0;i--) { for(j=5000;j>0;j--); } } //------------------------------------------------------------------------------------------------- //================================================================================================= int IIC_Handler; // static struct input_dev *OFN_dev; //-------------------------------------------------------------------------------------------------- static irqreturn_t KeyOFN_isr(int irq, void *dev_id) //中断0 处理函数 { /*get pin value <down 0, up 1> */ int val = gpio_get_value (S5PV210_GPH0(0)); // s3c2410_gpio_getpin(S3C2410_GPG(0)); /* val must a variable */ printk("Enter EIENT0 ! \n"); input_report_key(OFN_dev,KEY_5, !val); input_sync(OFN_dev); delay(); input_report_key(OFN_dev,KEY_5, !!val); input_sync(OFN_dev); return IRQ_RETVAL(IRQ_HANDLED); } //-------------------------------------------------------------------------------------------------- static irqreturn_t MotionOFN_isr(int irq, void *dev_id) //中断1处理函数 { char buf[3]; buf[0] = 2; int val = gpio_get_value (S5PV210_GPH0(1)); printk("Enter IRQ_EINT1,MOtionOFN_isr~!--hello1--\n"); dvcIIC_write( buf, 1); //发送地址 dvcIIC_read ( buf, 3); //从地址2读取三位 printk("OFN return 0x%x--0x%x--0x%x\n", buf[0],buf[1],buf[2]); if((buf[0]&1)&&(buf[0]!=0xff)) // OFN { if(buf[1] > 0xF0 ) { input_report_key(OFN_dev,KEY_LEFT, !val); input_sync(OFN_dev); input_report_key(OFN_dev,KEY_LEFT, !!val); input_sync(OFN_dev); delay(); } else { input_report_key(OFN_dev,KEY_RIGHT, !val); input_sync(OFN_dev); input_report_key(OFN_dev,KEY_RIGHT, !!val); input_sync(OFN_dev); delay(); } if(buf[2] > 0xF0 ) { input_report_key(OFN_dev,KEY_UP, !val); input_sync(OFN_dev); input_report_key(OFN_dev,KEY_UP, !!val); input_sync(OFN_dev); delay(); } else { input_report_key(OFN_dev,KEY_DOWN, !val); input_sync(OFN_dev); input_report_key(OFN_dev,KEY_DOWN, !!val); input_sync(OFN_dev); delay(); } delay(); } return IRQ_RETVAL(IRQ_HANDLED); } //-------------------------------------------------------------------------------------------------- static int __init OFN_init(void) // { char buf1[10]; int ret = 0; char buffer[2]; InterfaceInit (); // IIC 接口初始化 printk("--1\n"); gpio_direction_input(S5PV210_GPH0(0)); gpio_direction_input(S5PV210_GPH0(1)); s3c_gpio_cfgpin(S5PV210_GPH0(0), S3C_GPIO_SFN(0x0000000f)); //设置为外部中断 eint0 ,参考GP0CON【】 s3c_gpio_cfgpin(S5PV210_GPH0(1), S3C_GPIO_SFN(0x000000f0)); set_irq_type(IRQ_EINT0, IRQ_TYPE_EDGE_FALLING); set_irq_type(IRQ_EINT1, IRQ_TYPE_EDGE_FALLING); //------------------------------------------------------------------------- OFN_dev = input_allocate_device(); // if (!OFN_dev) return -ENOMEM; OFN_dev->name = "Mini Optical Finger Navigation Module"; OFN_dev->phys = "OFN/OFN0"; OFN_dev->id.bustype = BUS_HOST; OFN_dev->id.vendor = 0x0001; OFN_dev->id.product = 0x0001; OFN_dev->id.version = 0x0100; set_bit(EV_KEY,OFN_dev->evbit); set_bit(KEY_5,OFN_dev->keybit); set_bit(KEY_LEFT,OFN_dev->keybit); set_bit(KEY_RIGHT,OFN_dev->keybit); set_bit(KEY_UP,OFN_dev->keybit); set_bit(KEY_DOWN,OFN_dev->keybit); //--------------------------------------------------------------------------- printk("--2\n"); ret = request_irq(IRQ_EINT0, KeyOFN_isr, IRQ_TYPE_EDGE_FALLING, "OFN0", NULL); //EINT0 注册 if(ret) { printk(KERN_ERR "OFN0: unable to allocate VSYNC interrupt\n"); input_free_device(OFN_dev); return -EBUSY; } ret = request_irq(IRQ_EINT1, MotionOFN_isr, IRQF_SHARED, "OFN1", OFN_dev); //EINT1 注册 if(ret) { printk(KERN_ERR "OFN1: unable to allocate VSYNC interrupt\n"); input_free_device(OFN_dev); return -EBUSY; } //-------------------------------------------------------------------------------- ret = input_register_device(OFN_dev); if(ret) { free_irq(IRQ_EINT0, OFN_dev); free_irq(IRQ_EINT1, OFN_dev); input_free_device(OFN_dev); return -1; } //-------------------------------------------------------------------------------- buffer[0]=0x13; buffer[1] = 2; // dvcIIC_write( buffer, 2); delay(); buffer[0]=0x15; buffer[1] = 3; // 初始化 dvcIIC_write( buffer, 2); delay(); buf1[0] = 0; dvcIIC_write( buf1, 1); delay(); dvcIIC_read( buf1, 1); printk("OFN return 0x%x--0x%x--0x%x\n", buf1[0],buf1[1],buf1[2]); delay(); buf1[0] = 2; dvcIIC_write( buf1, 1); delay(); dvcIIC_read( buf1, 3); printk("OFN return 0x%x--0x%x--0x%x\n", buf1[0],buf1[1],buf1[2]); delay(); return 0; } //-------------------------------------------------------------------------------------------------- static void __exit OFN_exit(void) // { free_irq(IRQ_EINT0, NULL); // free_irq(IRQ_EINT1, OFN_dev); input_unregister_device(OFN_dev); // } //-------------------------------------------------------------------------------------------------- MODULE_LICENSE("GPL"); MODULE_AUTHOR("LIGHT"); module_init(OFN_init); // module_exit(OFN_exit); // //--------------------------------------------------------------------------------------------------
按键中断输入 按键事件 传送信息驱动实现。input输入设备注册。
转载自:http://blog.csdn.net/bmbm546/article/details/7024047