现在的位置: 首页 > 综合 > 正文

Button input interrupt under linux kernel 2.6.35.7 send message to touch screen

2013年10月27日 ⁄ 综合 ⁄ 共 8829字 ⁄ 字号 评论关闭

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

抱歉!评论已关闭.