input子系统(与平台总线结合)②

数据结构:

#ifndef __PLAT_INPUT_H__
#define __PLAT_INPUT_H__

//定义按键信息
struct btn_info{
	char * name;
	int gpiono;
	struct input_event event;
};

//设计一个平台自定义数据的类型
struct btn_platdata {
	struct btn_info * key_set;
	int key_size;
};

struct btn_input_dev{
  	struct device dev;//父类
    struct input_dev *i_dev;//输入设备
	struct btn_platdata *pd;
};
#endif

设备层:

#include <linux/init.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/gpio.h>
#include <linux/input.h>
#include "plat_input.h"
//准备四个按键的信息(包括名字。gpio,事件类和动作,以及动作。even.value在驱动层中断中上报)
struct btn_info btn_set[] = {
	[0]= {
		.name = "key_up",
	    .gpiono = S5PV210_GPH0(0),
		.event = {
			.type = EV_KEY,
			.code = KEY_UP,
		},
	},
	[1]= {
		.name = "key_down",
		.gpiono = S5PV210_GPH0(1),
		.event = {
			.type = EV_KEY,
			.code = KEY_DOWN,
		},
	},
	[2]= {
		.name = "key_left",
		.gpiono = S5PV210_GPH0(2),
		.event = {
			.type = EV_KEY,
			.code = KEY_LEFT,
		},
	},
	[3]= {
		.name = "key_right",
		.gpiono = S5PV210_GPH0(3),
		.event = {
			.type = EV_KEY,
			.code = KEY_RIGHT,
		},
	},
};
//平台自定义数据
struct btn_platdata btn_input_pdata = {
	.key_set = btn_set,
	.key_size = ARRAY_SIZE(btn_set),
};


void btn_input_release(struct device *dev)
{
	printk("---------------%s---------------\n",__FUNCTION__);

}

//?????pdev
struct platform_device input_pdev = {
	.name = "s5pv210_key",
	.id = -1,
	.dev = {
		.release = btn_input_release,
		.platform_data = &btn_input_pdata,//自定义数据传递给平台输入设备
	},
};


static int __init plat_input_dev_init(void)
{
	printk("---------------%s---------------\n",__FUNCTION__);
	return platform_device_register(&input_pdev);
}

static void __exit plat_input_dev_exit(void)
{
	printk("---------------%s---------------\n",__FUNCTION__);
	platform_device_unregister(&input_pdev);
}
module_init(plat_input_dev_init);
module_exit(plat_input_dev_exit);
MODULE_LICENSE("GPL");

驱动层:

#include <linux/init.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/slab.h>
#include <linux/interrupt.h>
#include <linux/gpio.h>
#include <linux/input.h>
#include "plat_input.h"

struct btn_input_dev *keydev;
int irqno;

irqreturn_t button_interrupt(int gpiono, void * pdata)//pdata是request_irq的最后一个参数此处为按键信息接结构体
{
    int value;
	struct btn_info * tmp;
	struct input_event event;
	printk("---------------%s---------------\n",__FUNCTION__);
	tmp = (struct btn_info *)pdata;
	event = (struct input_event)tmp->event;
	
	value = gpio_get_value(tmp->gpiono);
	if(value)
	{
		//松开
		event.value = 0;//为value赋值然后上报
		input_event(keydev->i_dev, event.type,event.code,event.value);
		input_sync(keydev->i_dev);
	}
	else//按下
	{
		event.value = 1;
		input_report_key(keydev->i_dev,event.code,event.value);
		input_sync(keydev->i_dev);
	}
	return IRQ_HANDLED;
}

int input_btn_probe(struct platform_device *pdev)
{
    int ret,i;
	struct btn_info *kinfo;
	
	printk("---------------%s---------------\n",__FUNCTION__);
	
    //0. 分配一个全局对象
	keydev = kzalloc(sizeof(struct btn_input_dev),GFP_KERNEL);//用来接收输入设备自定义数据
	if(keydev == NULL)//错误处理
    {
		printk("kzalloc error");
		return -ENOMEM;
	}
	//1. 获取自定义数据
	keydev->pd = pdev->dev.platform_data;
	/*
	struct btn_platdata {
	struct btn_info * key_set;//四个按键信息包括event事件
	int key_size;
	};
	*/
	
	//2. 分配一个input_device对象
	keydev->i_dev = input_allocate_device();
	if(keydev->i_dev == NULL)
	{
		printk("input_allocate_device error");
		ret = -ENOMEM;
		goto err_kfree;
	}
	//3. 初始化input_device对象
	keydev->i_dev->evbit[0] = BIT_MASK(EV_KEY);

	//4. 注册input_device对象
	ret = input_register_device(keydev->i_dev);
	if(ret)
	{
		printk("input_register_device error");
		goto err_free_dev;
	}
	//5. 硬件初始化
	for(i = 0; i < keydev->pd->key_size; i++)
	{
		kinfo = &keydev->pd->key_set[i];//获取按键结构体信息并为每一个按键申请一个中断
		irqno = gpio_to_irq(kinfo->gpiono);//通过gpio获取中断号
		if(request_irq(irqno,button_interrupt,IRQF_TRIGGER_FALLING|IRQF_TRIGGER_RISING,kinfo->name,kinfo))
		{
			printk("request_irq error");
			ret = -EBUSY;
			goto err_unregister_dev;
		}
		//设置能产生哪些按键数据
		set_bit(kinfo->event.code,keydev->i_dev->keybit);//同button_dev->keybit[BIT_WORD(KEY_DOWN)] = BIT_MASK(KEY_DOWN);
	}
	return 0;
	err_unregister_dev:
	{
		for(; i > 0; i--)
		{
			irqno = gpio_to_irq(keydev->pd->key_set[i-1].gpiono);
			free_irq(irqno,&(keydev->pd->key_set[i-1]));
		}
        input_unregister_device(keydev->i_dev);
	}
	err_free_dev:
		input_free_device(keydev->i_dev);
	err_kfree:
		kfree(keydev);
	return ret;
}

int input_btn_remove(struct platform_device *pdev)
{
    int i;
	printk("---------------%s---------------\n",__FUNCTION__);
	for(i = 0; i < keydev->pd->key_size; i++)
	{
	    irqno = gpio_to_irq(keydev->pd->key_set[i].gpiono);
		free_irq(irqno,&(keydev->pd->key_set[i]));
	}
	input_unregister_device(keydev->i_dev);
	input_free_device(keydev->i_dev);
	kfree(keydev);
	return 0;
}

struct platform_driver input_pdrv = {
	.probe = input_btn_probe,//执行probe方法
    .remove = input_btn_remove,
	.driver = {
		.name = "s5pv210_key",
	},
};

static int __init plat_input_drv_init(void)
{
	printk("---------------%s---------------\n",__FUNCTION__);
	return platform_driver_register(&input_pdrv);
}

static void __exit plat_input_drv_exit(void)
{
	printk("---------------%s---------------\n",__FUNCTION__);
	platform_driver_unregister(&input_pdrv);
}

module_init(plat_input_drv_init);
module_exit(plat_input_drv_exit);
MODULE_LICENSE("GPL");

app:

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

int main(int argc, char *argv[])
{
	int fd;
	int ret;
    struct input_event event;

	fd = open("/dev/event0",O_RDWR);
	if(fd < 0)
	{
		perror("open");
		exit(1);
	}
	while(1)
	{
       ret = read(fd, &event, sizeof(struct input_event));input子系统结构返回的event事件结构体(由中断上报影响里面的值)
	   if(ret < 0)
	   {
		   perror("read");
		   exit(1);
	   }
	   if(event.type == EV_KEY)
	   {

	      switch(event.code)
	      {
			case KEY_UP:
				if(event.value)
					printf("app按下---->上键\n");
				else
					printf("app松开---->上键\n");
				break;
			case KEY_DOWN:
				if(event.value)
					printf("app按下---->下键\n");
				else
					printf("app松开---->下键\n");
				break;
			case KEY_LEFT:
				if(event.value)
					printf("app按下---->左键\n");
				else
					printf("app松开---->左键\n");
				break;
			case KEY_RIGHT:
				if(event.value)
					printf("app按下---->右键\n");
				else
					printf("app松开---->右键\n");
				break;
			default:
				break;
		  }
	   }
	}
	close(fd);
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值