tiny4412 Linux驅動Input子系統

輸入設備(如鼠標,鍵盤,觸摸屏,撥碼開關,按鍵,麥克風,遊戲搖桿,遊戲手柄等)是典型的字符設備。Linux爲了方便統一管理這些設備,然後設計了輸入子系統,在Linux中,輸入子系統的驅動節點都是有固定的位置的:

在新內核中:
    /dev/input/event0 /dev/input/event1 ...
    /dev/input/mouse0 /dev/input/mouse1 ...
在舊內核中:
    /dev/event0 /dev/event1 ...
    /dev/mouse0 /dev/mouse1 ...

驅動節點對應哪個設備

cat /proc/bus/input/devices

控制檯捕獲驅動節點的信息:

hexdump /dev/input/event0

本次是以4個key按鍵爲例,來編寫一個輸入子系統,設計一個小鍵盤驅動,模擬qwer按鍵,當分別按下開發板上的4個按鍵時,應用層打印一些內容,驗證驅動是否成功。

驅動層input.c

#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/input.h>
#include <linux/gpio.h>
#include <mach/gpio.h>
#include <linux/interrupt.h>

#define KEY_GPIO(i) EXYNOS4_GPX3(2+i)
#define KEY_QWER(i) (KEY_Q+i)

struct input_dev *key_dev;
int key_irq[4]={0};
irqreturn_t key_irq_handle(int irq, void *args)
{
	int i=0;
		for(i = 0; i < 4; i++){
			if(irq==key_irq[i]){
			 	//printk("key%d Down!\n", i+1);	
				input_report_key(key_dev, KEY_QWER(i), !!!gpio_get_value(KEY_GPIO(i)));
				input_sync(key_dev);
			}
		}
	return IRQ_HANDLED;
}

static int __init tiny4412_input_init(void)
{
	int ret;
	int i;
	char name[16];
	key_dev = input_allocate_device();
	if(key_dev == NULL){
		printk("input alloc error\n");
		return -1;
	}

	key_dev->name = "biu's mechanical keyboard";

	//把evbit數組裏的EV_KEY位使能,也就表明這個設備是一個key設備
	set_bit(EV_KEY, key_dev->evbit);
	//讓該設備支持qwer鍵
	for(i=0;i<4;i++){
		set_bit(KEY_QWER(i), key_dev->keybit);
	}
	
	for(i=0; i<4; i++){
		memset(name, 0, sizeof(name));
		sprintf(name, "key%d_irq", i);
		key_irq[i] = gpio_to_irq(KEY_GPIO(i));
		ret = request_irq(key_irq[i], key_irq_handle, IRQF_DISABLED | IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING,name, (void*)i);
		if(ret < 0){
			printk("request irq error\n");
			goto err_irq;
		}
	}
	
	ret = input_register_device(key_dev);
	if(ret < 0){
		printk("input register error\n");
		goto err_input;
	}
	
	return 0;
	err_input:
	while(i--){
		free_irq(key_irq[i], NULL);
	}
	err_irq:
	input_free_device(key_dev);
	return ret;
}

static void __exit tiny4412_input_exit(void)
{
	int i = 4;
	while(i--){
		free_irq(key_irq[i], (void*)i);
	}
	input_unregister_device(key_dev);
	input_free_device(key_dev);
}

module_init(tiny4412_input_init);
module_exit(tiny4412_input_exit);

MODULE_LICENSE("GPL");

 應用層app_input.c

#include <stdio.h>
#include <sys/types.h>
#include <sys/fcntl.h>
#include <sys/stat.h>
#include <unistd.h>
#include <linux/input.h>

int main(int argc, char **argv)
{
	int fd;
	struct input_event event;
	fd = open(argv[1],O_RDWR);
	if(fd < 0){
		perror("open error:");
		return fd;
	}

	while(1){
		read(fd,&event,sizeof(event));
		
		if(event.type == EV_KEY){
			if(event.code == KEY_Q){
					printf("Q:霸王拳\n");
				}
			 if(event.code == KEY_W){
					printf("W:降龍十八掌\n");
				}
			 if(event.code == KEY_E){
					printf("E:狂龍亂舞\n");
				}
			 if(event.code == KEY_R){
					printf("R:流星趕月\n");
				}
		}
		
	}

	close(fd);
	return 0;
}

Makefile

obj-m += input.o
KERN_DIR=/root/work/tiny4412/linux/linux-3.5
PWD := $(shell pwd)

modules:
	$(MAKE) ARCH=arm -C $(KERN_DIR) M=$(PWD) modules
	arm-linux-gcc app_input.c -o app
	cp app input.ko /root/work/tiny4412/rootfs/root_nfs/root/input
clean:
	$(MAKE) ARCH=arm -C $(KERN_DIR) M=$(PWD) modules clean
	

運行測試:

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章