我们前面讲的好像有点问题:
1)我们编写的设备模块,不是再编译的时候和核心层的input.c、调用层的evdev.c结合然后一起编译。
正解是,我设备本来就是一个模块,而核心层也是一个模块,调用层也是一个模块。只不过内核在运行的时候就已经把核心层和调用层的资源加载进去在内核里了。当我们的设备模块装载到内核中之后,内核就会调用核心和调用层的模块,组成一个完整的驱动。
2)那个set_bit函数也并不是把那个ev_key写到evdev里面去:这个函数是把ev_dev的里面的ev_key的位置一:
3)关于event,这个设备文件是在,调用的时候申请的设备节点。那么是所有的设备节点都叫event?
如果是那么为什么里面还有mouse等设备节点,如果不是,那为什么event里面也可以表示鼠标等输入系统。
所以,event事件、mouse鼠标的关系是什么?
——————————————————————————————————————————————————
这里我们来详细讲解之前的那些函数具体做了什么?
首先第一步我们创建了一个设备对象(实例化输入设备结构体对象):
struct input_dev *inputdev;
这个设备结构体里面有什么?
struct input_dev {//表示的是一个具体的输入设备,描述设备能够产生什么数据
const char *name; // sysfs中给用户看的信息
const char *phys;
const char *uniq;
struct input_id id;
//evbit实际是一个位表,描述输入设备能够产生什么类型数据
unsigned long evbit[BITS_TO_LONGS(EV_CNT)]; // EV_KEY,EV_ABS, EV_REL
//表示能够产生哪种按键
unsigned long keybit[BITS_TO_LONGS(KEY_CNT)];//KEY_POWER.. 能够表示768bit,直接用24个long来表示
// KEY_CNT == 768 BITS_TO_LONGS== nr/32 = 768/32==24
//表示能够产生哪种相对坐标数据
unsigned long relbit[BITS_TO_LONGS(REL_CNT)];// REL_X
//表示能够产生哪种绝对坐标数据
unsigned long absbit[BITS_TO_LONGS(ABS_CNT)]; //ABS_X
unsigned long mscbit[BITS_TO_LONGS(MSC_CNT)];
unsigned long ledbit[BITS_TO_LONGS(LED_CNT)];
unsigned long sndbit[BITS_TO_LONGS(SND_CNT)];
unsigned long ffbit[BITS_TO_LONGS(FF_CNT)];
unsigned long swbit[BITS_TO_LONGS(SW_CNT)];
struct device dev; // 继承device对象
struct list_head h_list;
struct list_head node; //表示节点
}
这个结构体其实非常庞大:上面是一些比较重要的一些信息。
0~3:
首先前四个:添加用户信息
表示:我们自定义的设备信息。我们的这个设备叫什么,以及版本号什么什么的,就是你把这个信息打上去就会再查看这个设备信息的时候打印出来,告诉用户。
直接用:input->name = “key1”…这样去初始化设备信息。
4:
第四个数据:表示产生的数据类型
unsigned long evbit[BITS_TO_LONGS(EV_CNT)]; // EV_KEY,EV_ABS, EV_REL
这其实是一个32位的一个位表,每一位表示对应的那种数据类型。
那我们的输入设备会产生很多一种数据:
eg:1,按键/keyboard: 产生键值,实际是一个数字
#define KEY_VOLUMEDOWN 114
#define KEY_VOLUMEUP 115
#define KEY_POWER 116 /* SC System Power Down */
2,ts/gsensor:产生坐标,绝对坐标, 有一个明确坐标系,并且原点(0,0),最大值(800,480)
#define ABS_X 0x00
#define ABS_Y 0x01
#define ABS_PRESSURE 0x18
#define ABS_MT_TOUCH_MAJOR 0x30 /* Major axis of touching ellipse */
#define ABS_MT_TOUCH_MINOR 0x31 /* Minor axis (omit if circular) */
#define ABS_MT_WIDTH_MAJOR 0x32 /* Major axis of approaching ellipse */
#define ABS_MT_WIDTH_MINOR 0x33 /* Minor axis (omit if circular) */
#define ABS_MT_ORIENTATION 0x34 /* Ellipse orientation */
#define ABS_MT_POSITION_X 0x35 /* Center X touch position */
#define ABS_MT_POSITION_Y 0x36 /* Center Y touch position */
3,mouse:产生坐标,相对坐标,坐标值是相对于之前一个点坐标
#define REL_X 0x00
#define REL_Y 0x01
#define REL_WHEEL 0x08
那么我们怎么去区分这些信号就是在:evbit这个位表,你给哪一位置一,就表示你这个数据是哪一位的。
比如我这个是一个按键信号:
我就可以用:_set_bit(EV_KEY,inputdev->evbit);
#define EV_KEY 0x01
去把evbit里面表示ev_key的位置一,可以看到我们的ev_key是第一位
把它置一就会产生这个效果:内核知道你这是一个ev_key类型的数据,这也相当于一个开关,你把这个开关打开,你的数据才能发到调用层。
5;第五个成员:表示按键的具体信息
unsigned long keybit[BITS_TO_LONGS(KEY_CNT)];/ /KEY_POWER… 能够表示768bit,直接用24个long来表示
这个是一个768位的而一个数组,用来存储你的按键是上面的具体表示类型。
比如:我想把这个按键,按下去就代表我按了一个ESC键,那么你就把keybit对应的esc键的位置置一就表示这个按键表示esc
当然 你想把这个按键设置成12345qewrrtyuiopasdfghjklzxcvbnm…这些按键都可以。
_set_bit(KEY_POWER, inputdev->keybit);
#define KEY_POWER 116`在这里插入代码片`
这就代表你把166位置成一,表示你的这个按键是一个power键。这样你发的数据就会带上key_power这个数据
当然你也可以不用函数,直接手写把166置一。是一个768位 768/32个long型数据
inputdev->keybit[116/32] |= 1 << 116%32;// 116%32;
由于我们是一个按键所以没有相对坐标等信息
所以:5~12 这个几个Long型的数据就是产生的数据的具体信息。
13:struct device dev; // 继承device对象
表示继承的device对象,拥有所有的device的属性,并做了些扩展,这就是继承
14:
15:表示我们这个设备的信息节点,它可以注册到核心层中,与调用层进行匹配
——————————————————————————————————————————————————
三、数据上报:
我们上次看到我们数据上报 的时候使用:
void input_event(struct input_dev *dev,unsigned int type, unsigned int code, int value)
会把:设备数据类型(按键、绝对坐标、相对坐标…)
设备数据具体表示(某个具体按键、具体坐标…)
数据状态:0/1—————表示这个数据的状态,比如我传了一个1那么表示我的esc这个键被按下去了,它就会
去执行esc这个数据或中断的处理。
这三个数据做成一个包发给调用层。
方法2:封装:
input_report_key(struct input_dev * dev, unsigned int code, int value)
input_event(dev, EV_KEY, code, !!value); //上报按键的时候一定0或者1
还可以用这种方法上报数据:
!! value:这个上报按键的时候一定0或者1,用法比较巧妙,例如我传的value是5 那么 !value就是0 那么!(!value)就是1;
所以两个!!的作用就是保证上报按键的时候一定0或者1。
————————————————————————————————————————————