input子系统_I2C

【一】input子系统

【1】input_dev结构体:
struct input_dev {      
       void *private;
       const char *name;  //设备名字
       const char *phys;  //文件路径,比如 input/buttons
       const char *uniq;   
       struct input_id id;

       unsigned long evbit[NBITS(EV_MAX)];  //表示支持哪类事件,常用有以下几种事件(可以多选)
       //EV_SYN       同步事件,当使用input_event()函数后,就要使用这个上报个同步事件
       //EV_KEY       键盘事件
       //EV_REL       relative相对坐标事件,比如鼠标
       //EV_ABS       absolute绝对坐标事件,比如摇杆、触摸屏感应
       //EV_MSC       其他事件
       //EV_LED       LED灯事件
       //EV_SND       sound声音事件

       //EV_REP       重复键盘按键事件
       //(内部会定义一个定时器,若有键盘按键事件一直按下/松开,就重复定时,时间一到就上报事件)   

       //EV_FF            受力事件
       //EV_PWR        电源事件
       //EV_FF_STATUS  受力状态事件

       /* 键盘变量定义在:include/linux/input.h, 比如: KEY_L(按键L) */
       unsigned long keybit[NBITS(KEY_MAX)];  		//存放支持的键盘按键值
       unsigned long relbit[NBITS(REL_MAX)];    		//存放支持的相对坐标值
       unsigned long absbit[NBITS(ABS_MAX)];   		//存放支持的绝对坐标值
       unsigned long mscbit[NBITS(MSC_MAX)];  		//存放支持的其它事件,也就是功能
       unsigned long ledbit[NBITS(LED_MAX)];   		//存放支持的各种状态LED
       unsigned long sndbit[NBITS(SND_MAX)];    		//存放支持的各种声音
       unsigned long ffbit[NBITS(FF_MAX)];       		//存放支持的受力设备
       unsigned long swbit[NBITS(SW_MAX)];     		//存放支持的开关功能

    int (*open)(struct input_dev *dev);
    void (*close)(struct input_dev *dev);	
	... ...
}

void set_bit(int nr, unsigned long *addr)
功能:设置位图
参数:
    @nr       值
    @addr   地址

struct input_dev *input_allocate_device(void);
功能:分配input_dev结构体空间
参数:
    @void
返回值:成功返回分配好的空间首地址,失败返回NULL

void input_free_device(struct input_dev *dev);
功能:释放input_dev空间

int  input_register_device(struct input_dev *);
功能:想内核注册input_dev
参数:
    @input_dev结构体指针
返回值:成功返回0,失败返回负数错误码
void input_unregister_device(struct input_dev *);
功能:注销input_dev

注:input是对字符设备驱动的封装,它在底层实现了file_operations
这一套机制而不用我们去填充了,只需按照以上流程即可完成驱动。

void input_event(struct input_dev *dev, unsigned int type, unsigned int code, int value);
功能:上报事件
参数:
@dev input_dev结构体指针
@type 事件类型 eg:EV_KEY
@code 具体的类型值 eg:KEY_F1
@value 事件状态值 eg:按下去0,抬起 1

void input_report_key(struct input_dev *dev, unsigned int code, int value)
功能:上报按键事件
参数:
@dev input_dev结构体指针
@code 具体的类型值 eg:KEY_F1
@value 事件状态值 eg:按下去0,抬起 1

void input_sync(struct input_dev *dev)
功能:上报同步事件

struct input_event {
struct timeval time;
__u16 type;
__u16 code;
__s32 value;
};
驱动代码:
/*********************************************************************
*Copyright © 2019 1000phone
*kernel_pthread
*Date and Dition: 2019-05-31 v1.0
*Author:yuwei@1000phone.com
********************************************************************/
#include <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/kthread.h>
#include <linux/device.h>
#include <linux/gpio.h>
#include <linux/fs.h>
#include <linux/interrupt.h>
#include <linux/timer.h>
#include <linux/input.h>

#define DEVCOUNT 3
#define NAME “s5p6818_keys”

#define KEY_A_28 (320 + 28)
#define KEY_B_9 (32
1 + 9)

#define Debug_log(level)
printk(level “—%s—%s—%d—\n”,FILE,func,LINE)

struct s5p6818_key{
struct task_struct *task;
struct input_dev *xinput;
int irqno0,irqno1;
struct timer_list tm;
};

struct s5p6818_key key;

void key_timer_func(unsigned long args)
{

if(args == key.irqno0){
	if(!gpio_get_value(KEY_A_28)){
		printk("----KEY_A_28_down----\n");
		input_event(key.xinput,EV_KEY,KEY_L,0);
		input_sync(key.xinput);
	}else{
		printk("----KEY_A_28_up----\n");
		input_event(key.xinput,EV_KEY,KEY_L,1);
		input_sync(key.xinput);
	}
}
if(args == key.irqno1){
	if(!gpio_get_value(KEY_B_9)){
		printk("----KEY_B_9_down----\n");
		input_event(key.xinput,EV_KEY,KEY_S,0);
		input_sync(key.xinput);
	}else{
		printk("----KEY_B_9_up----\n");
		input_event(key.xinput,EV_KEY,KEY_S,1);
		input_sync(key.xinput);
	}
}

}

irqreturn_t key_irq_handle(int irq, void *arg)
{
if(irq == key.irqno0){
key.tm.data = irq;
mod_timer(&(key.tm),jiffies+HZ/50);
}
if(irq == key.irqno1){
key.tm.data = irq;
mod_timer(&(key.tm),jiffies+HZ/50);
}

return IRQ_HANDLED;

}

int gpio_keys_open(struct input_dev *dev)
{
Debug_log(KERN_INFO);
return 0;
}
void gpio_keys_close(struct input_dev *dev)
{
Debug_log(KERN_INFO);
}

static int __init demo_init(void)
{
int ret;

key.xinput = input_allocate_device();
if(NULL == key.xinput){
	printk(KERN_ERR "input_allocate_device...\n");
	ret = -ENOMEM;
	goto err0;
}

(key.xinput)->name = "s5p6818_key";
(key.xinput)->phys = "gpio-keys";
(key.xinput)->open = gpio_keys_open; 
(key.xinput)->close = gpio_keys_close;
//(key.xinput)->id.bustype = BUS_HOST;

set_bit(EV_KEY,(key.xinput)->evbit);
//set_bit(EV_REL,(key.xinput)->evbit);
set_bit(EV_SYN,(key.xinput)->evbit);

set_bit(KEY_L,(key.xinput)->keybit);
set_bit(KEY_S,(key.xinput)->keybit);

ret = input_register_device((key.xinput));
if(ret < 0){
	printk(KERN_INFO "input_register_device failed...\n");
	goto err1; 
}

key.irqno0 = gpio_to_irq(KEY_A_28);
key.irqno1 = gpio_to_irq(KEY_B_9);

ret = request_irq(key.irqno0,key_irq_handle,IRQF_TRIGGER_RISING|IRQF_TRIGGER_FALLING,\
	"key_gpioa28",NULL);
if(ret < 0){
	printk(KERN_ERR "request_irq A28 failed...\n");
	goto err2;
}

ret = request_irq(key.irqno1,key_irq_handle,IRQF_TRIGGER_RISING|IRQF_TRIGGER_FALLING, \
	"key_gpiob9", NULL);
if(ret < 0){
	printk(KERN_ERR "request_irq B9 failed...\n");
	goto err3;
}

key.tm.expires = 0;
key.tm.function= key_timer_func;
init_timer(&(key.tm));

add_timer(&(key.tm));

Debug_log(KERN_INFO);
return 0;

err3:
free_irq(key.irqno0,NULL);
err2:
input_unregister_device(key.xinput);
err1:
input_free_device(key.xinput);
err0:
return ret;
}

static void __exit demo_exit(void)
{
del_timer(&(key.tm));
free_irq(key.irqno0,NULL);
free_irq(key.irqno1,NULL);
input_unregister_device(key.xinput);
input_free_device(key.xinput);
Debug_log(KERN_INFO);
}

module_init(demo_init);
module_exit(demo_exit);
MODULE_LICENSE(“GPL”);

MODULE_AUTHOR(“yuwei@1000phone.com”);
MODULE_DESCRIPTION(“This is a demo, about workqueue”);

应用层测试代码:
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <linux/input.h>
#include <stdio.h>
#include <errno.h>

struct input_event event;

int main(int argc, const char *argv[])
{
int fd;
fd = open(argv[1] , O_RDWR);
if(fd < 0){
perror(“open”);
return -EINVAL;
}
while(1){
if(!read(fd,&event,sizeof(struct input_event))){
perror(“read”);
return -EINVAL;
}
printf(“type:%d,code:%d,value:%d\n”,event.type,event.code,event.value);
//printf(“code:%d\n”,event.code);
//printf(“value:%d\n”,event.value);
printf("------------------------------------------------------------------------\n");
}
close(fd);
return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值