//****************************************************************
//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输入设备注册。