/****************************************************************
* OFN/ts.c
*
* Copyright (c) 2011-11-24
*
* 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/kernel.h>
#include <linux/slab.h>
#include <linux/poll.h>
#include <linux/delay.h>
#include <linux/device.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;
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--);
}
}
//-------------------------------------------------------------------------------------------------
//=================================================================================================
static struct input_dev *OFN_dev;
#define MiniX 10
#define MaxX 750
#define MiniY 10
#define MaxY 450
#define CenterX 380
#define CenterY 230
int absX = CenterX;
int absY = CenterY;
//--------------------------------------------------------------------------------------------------
static irqreturn_t KeyOFN_isr(int irq, void *dev_id) //中断0 处理函数
{
printk("Enter EIENT0 ! \n");
input_report_abs(OFN_dev, ABS_X, absX); //X轴坐标
input_report_abs(OFN_dev, ABS_Y, absY); //Y轴坐标
input_report_key(OFN_dev, BTN_TOUCH, 1); //按下 按键
input_report_abs(OFN_dev, ABS_PRESSURE, 1); //按下 压力
input_sync(OFN_dev); //事件同步
input_report_key(OFN_dev, BTN_TOUCH, 0); //抬起 按键值 此两条抬起信息必须添加
input_report_abs(OFN_dev, ABS_PRESSURE, 0); //抬起 压力值
input_sync(OFN_dev); //事件同步
delay();
return IRQ_RETVAL(IRQ_HANDLED);
}
//--------------------------------------------------------------------------------------------------
static irqreturn_t MotionOFN_isr(int irq, void *dev_id) //中断1处理函数
{
char buf[3];
buf[0] = 2;
printk("Enter IRQ_EINT1,MOtionOFN_isr~!--hello1--\n");
dvcIIC_write( buf, 1); //发送地址
dvcIIC_read ( buf, 3); //从地址2,3,4 读取三位数据
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 ) //判断X轴向
{
absX = (CenterX+(buf[1])/2);
if( absX > MaxX )
{
absX = MaxX;
}
}
else
{
absX = (CenterX-(0xF0 - buf[1])/2);
if( absX < MiniX )
{
absX = MiniX;
}
}
if(buf[2] > 0xF0 ) //判断Y轴向
{
absY = (CenterY+(buf[2])/2);
if( absY > MaxY )
{
absY = MaxY;
}
}
else
{
absY = (CenterY-(0xF0 - buf[2])/2);
if( absY < MiniY )
{
absY = MiniY;
}
}
input_report_abs(OFN_dev, ABS_X, absX);
input_report_abs(OFN_dev, ABS_Y, absY);
input_sync(OFN_dev); //坐标信息同步
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)); //设置为外部中断 eint1 ,参考GP0CON【】
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 = "TouchScreen Pipe"; // 触摸屏设备属性信息
OFN_dev->phys = "input(ts)";
OFN_dev->id.bustype = BUS_RS232;
OFN_dev->id.vendor = 0xDEAD;
OFN_dev->id.product = 0xBEEF;
OFN_dev->id.version = 0x0101;
input_set_abs_params(OFN_dev, ABS_X, 0, 0x320, 0, 0); // 800
input_set_abs_params(OFN_dev, ABS_Y, 0, 0x1E0, 0, 0); // 480
input_set_abs_params(OFN_dev, ABS_PRESSURE, 0, 1, 0, 0); // 压力
OFN_dev->evbit[0] = BIT_MASK(EV_SYN) | BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
OFN_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH);
//---------------------------------------------------------------------------
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输入设备注册。