Tiny6410 + Linux2.6.38 + input子系统 + 按键中断模拟系统键盘输入的例程

60 篇文章 0 订阅
44 篇文章 1 订阅

Linux下使用按钮来模拟键盘中“Left","Right","Tab","Space"输入的例程,已经过本人测试,总结在此以供参考。

驱动程序代码:

/***********************************************************************************
  Tiny6410 + Linux2.6.38 + 按钮中断驱动 + linux输入子系统 来使用按键模拟键盘输入的例程。
 ***********************************************************************************/
#include <linux/input.h>
#include <linux/module.h>
#include <linux/init.h>
#include <asm/irq.h>
#include <asm/io.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/init.h>
#include <linux/delay.h>
#include <linux/poll.h>
#include <linux/irq.h>
#include <asm/irq.h>
#include <linux/interrupt.h>
#include <asm/uaccess.h>
#include <mach/regs-gpio.h>
#include <mach/hardware.h>
#include <linux/platform_device.h>
#include <linux/cdev.h>
#include <linux/miscdevice.h>
#include <linux/device.h>

#include <linux/gpio.h> 
#include <plat/gpio-cfg.h>
#include <mach/gpio-bank-n.h>
#include <mach/gpio-bank-l.h>
#include <mach/map.h>

static struct input_dev *button_dev; 
static irqreturn_t buttons_interrupt(int irq, void *dummy);
static int button_open(struct input_dev *dev);
static void button_close(struct input_dev *dev); 
struct button_irq_desc {
	int irq;          
	int number;         
	char *name;      
};

static struct button_irq_desc button_irqs [] = {
	{IRQ_EINT(11), 0, "KEY0"},    //IRQ_EINT(11)对应GPN11
	{IRQ_EINT(16), 1, "KEY1"},    //IRQ_EINT(16)对应GPL8
	{IRQ_EINT(17), 2, "KEY2"},    //IRQ_EINT(17)对应GPL9
	{IRQ_EINT(18), 3, "KEY3"},    //IRQ_EINT(18)对应GPL10
};

// 前面的处理方法和按钮中断驱动类似。
static int button_open(struct input_dev *dev)
{
	int i;
	int err = 0;

	set_irq_type(IRQ_EINT(11), IRQ_TYPE_EDGE_BOTH);  
	set_irq_type(IRQ_EINT(16), IRQ_TYPE_EDGE_BOTH);  
	set_irq_type(IRQ_EINT(17), IRQ_TYPE_EDGE_BOTH);      
	set_irq_type(IRQ_EINT(18), IRQ_TYPE_EDGE_BOTH);  

	for (i = 0; i < sizeof(button_irqs)/sizeof(button_irqs[0]); i++)
	{
		if (button_irqs[i].irq < 0) continue;
		err = request_irq(button_irqs[i].irq, buttons_interrupt, IRQF_SAMPLE_RANDOM, button_irqs[i].name, (void *)&button_irqs[i]);
		if (err) break;
	} 
	if (err) 
	{
		i--;
		for (; i >= 0; i--) 
		{
			if (button_irqs[i].irq < 0) continue;
			disable_irq(button_irqs[i].irq);
			free_irq(button_irqs[i].irq, (void *)&button_irqs[i]);
		}
		return -EBUSY;
	} 
	return 0;
} 


static void button_close(struct input_dev *dev)
{
	int i; 
	for (i = 0; i < sizeof(button_irqs)/sizeof(button_irqs[0]); i++) 
	{
		if (button_irqs[i].irq < 0) continue;
		disable_irq(button_irqs[i].irq);
		free_irq(button_irqs[i].irq, (void *)&button_irqs[i]);
	} 
} 


static irqreturn_t buttons_interrupt(int irq, void *dummy)
{
	input_report_key(button_dev, KEY_LEFT, !(readl(S3C64XX_GPNDAT)&(1<<11)));
	input_report_key(button_dev, KEY_RIGHT, !(readl(S3C64XX_GPLDAT)&(1<<8)));
	input_report_key(button_dev, KEY_MENU, !(readl(S3C64XX_GPLDAT)&(1<<9)));
	input_report_key(button_dev, KEY_SPACE, !(readl(S3C64XX_GPLDAT)&(1<<10)));    //将对应的事件报告给input子系统。
	input_sync(button_dev);
	return IRQ_HANDLED;
} 


static int __init button_init(void)
{
	int error;
	struct input_dev *input_dev;
	printk("smdk6410 my_keyboard module start/n");  
	input_dev = input_allocate_device();  
	if(!input_dev)  
	{  
		printk(KERN_ERR "Unable to allocate the input device!!/n");  
		return -ENOMEM;  
	}  
	button_dev = input_dev;  

	set_bit(EV_KEY, button_dev->evbit);      // 通过set_bit()告诉子系统支持哪些事件。
	set_bit(KEY_LEFT, button_dev->keybit);
	set_bit(KEY_RIGHT, button_dev->keybit);
	set_bit(KEY_MENU, button_dev->keybit);
	set_bit(KEY_SPACE, button_dev->keybit);

	button_dev->name = "buttons_tyc";
	button_dev->dev.init_name = "input_tyc";

	button_dev->open = button_open;
	button_dev->close = button_close;

	printk("input device has allocated/n");

	error = input_register_device(button_dev);
	if (error)
	{
		printk(KERN_ERR "button.c: Failed to register device\n");
		input_free_device(button_dev);
		return error;
	}
	printk("register device has success\n");
	return 0; 
} 


static void __exit button_exit(void)
{
	input_unregister_device(button_dev); 
} 


module_init(button_init);
module_exit(button_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("modelsim");


测试程序源码:

/***********************************
按键中断 + input子系统 测试程序。
***********************************/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/select.h>
#include <sys/time.h>
#include <errno.h>
#include <linux/input.h> 
int main(void)
{
	int fd;
	int key_value,i=0,count; 
	struct input_event ev_key;
	fd = open("/dev/input/event1", 666);    //这儿有可能是event0、event2、event3....
	if (fd < 0) 
	{
		perror("open device buttons");
		exit(1);
	} 
	for (;;) 
	{
		count = read(fd,&ev_key,sizeof(struct input_event)); 
		for(i=0; i<(int)count/sizeof(struct input_event); i++)
			if(EV_KEY==ev_key.type)
				printf("type:%d,code:%d,value:%d\n", ev_key.type,ev_key.code,ev_key.value); 
		if(EV_SYN==ev_key.type)
			printf("syn event\n\n");
	} 
	close(fd);
	return 0;
}

在此,感谢原作者的分享!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
1 引言 当前,由于Linux资源完全公开,使得Linux的发展日益广泛快速。基于Linux的各种应用已逐渐深入日常生活的方方面面,尤其是在嵌入式领域,由于内核可裁减定制,因此可随意地根据用户需求进行整个系统的定制与重构。其中,我们可以通过对各种标准外部设备的驱动进行改造,从而实现用户对标准设备的特定需求,例如可以通过对键盘的模拟来实现操作的自动化,从而可以避免重复的键盘操作。 2 Linux内核支持的外部调用接口 由于Linux内核作为系统最深层次的核心,因此外部的开发人员并不能直接对内核进行操作。然而在一些应用程序的开发过程中,又不得不使用内核的某些功能,因此就提供了一些外部接口供开发人员直接与底层内核打交道。 2.1 中断Linux 下,硬件中断叫做IRQ(Interrupt Requests)。有两种IRQ,短类型和长类型。短IRQ需要很短的时间,在此期间机器的其他部分被锁定,而且没有其他中断被处理。一个长IRQ需要较长的时间,在此期间可能发生其他中断(但不是发自同一个设备)。如果可能的话,最好把一个中段声明为长类型。如果CPU接到一个中断,它就会停止一切工作(除非它正在处理一个更重要的中断,在这种情况下要等到更重要的中断处理结束后才会处理这个中断),把相关的参数存储到栈里,然后调用中断处理程序。这意味着在中断处理程序本身中有些事情是不允许的,因为这时系统处在一个未知状态。解决这个问题的方法是让中断处理程序做需要马上做的事,通常是从硬件读取信息或给硬件发送信息,然后把对新信息的处理调度到以后去做。 实现的方法是在接到相关的IRQ(在Intel平台上有16个IRQ)时调用中断处理程序。这个函数接到IRQ号码、函数名、标志、一个/proc/interrupts的名字和传给中断处理程序的一个参数。标志中可以包括 SA_SHIRQ来表明你希望和其他处理程序共享此IRQ(通常很多设备公用一个IRQ),或者一个SA_INTERRUPT表明这是一个紧急中断。这个函数仅在此IRQ没有其他处理程序或需要共享所有处理程序时才会成功运行。 2.2 系统调用 系统调用发生在用户进程,通过一些特殊的函数来请求内核提供服务。这时,用户进程被挂起,内核验证用户请求,尝试执行并把结果反馈给用户进程,接着用户进程重新启动。一般当前系统的系统调用作为一张表sys_call_table进行定义的,是由指向实现各种系统调用的内核函数的函数指针组成的表。具体参数参见Linux内核源代码arch/i386/kernel/entry.S文件中: ENTRY(sys_call_table) l long SYMBOL_NAME(sys_ni_syscall) /* 0 - old "setup()" system call*/ l long SYMBOL_NAME(sys_exit) …

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值