Input设备驱动之事件类型
2015-08-08 16:19
302 查看
说明:输入子系统(input subsystem)的驱动层的核心结构。
头文件:include/linux/input.h
成员说明:
void*private;
//私有数据指针
char*name;
//设备名字,如键盘名字。
char*phys;
//设备文件节点名,如input/kbd0。
char*uniq;
//全球唯一的ID号。
struct input_id id; /*其他信息,如版本号*/
unsignedlong evbit[NBITS(EV_MAX);]
//该设备驱动所能支持的事件。
//EV_SYN 同步事件
//EV_KEY 键盘事件
//EV_REL 相对坐标事件,用于鼠标
//EV_ABS 绝对坐标事件,用于摇杆
//EV_MSC 其他事件
//EV_LED LED灯事件
//EV_SND 声音事件
//EV_REP 重复按键事件
//EV_FF 受力事件
//EV_PWR 电源事件
//EV_FF_STATUS 受力状态事件
unsignedlong keybit[NBITS(KEY_MAX)];
//键值存放表
unsignedlong relbit[NBITS(REL_MAX)];
//用于存放相对坐标值等
unsignedlong absbit[NBITS(ABS_MAX)];
//用于存放绝对坐标值等
unsignedlong mscbit[NBITS(MSC_MAX)];
//存放其他事件类型
unsignedlong ledbit[NBITS(LED_MAX)];
//存放表示各种状态的LED值
unsignedlong sndbit[NBITS(SND_MAX)];
//存放各种事件的声音
unsignedlong ffbit[NBITS(FF_MAX)];
//存放受力设备的属性
intff_effects_max;
//显然与受力效果有关,具体作用还不大清楚。
unsignedint keycodemax;
unsignedint keycodesize;
void *keycode;
//这三个不是很清楚,有点模糊理解。
unsignedint repeat_key;
//存放重复按键时的键值
structtimer_list timer;
//定时器
structpm_dev *pm_dev;
//考虑到有些设备可能有电源管理
structpt_regs *regs;
//不清楚
intstate;
//显然是表示一个状态,但不清楚具体是谁的状态
intsync;
//具体用于什么也不大清楚
intabs[ABS_MAX + 1];
//显然是与绝对坐标有关的,但具体的作用不清楚。
intrep[REP_MAX + 1];
//存放重复按键时的延时,系统依靠这个延时时间来判断重复按键
//rep[0]表示开始要重复按键时的延时时间,即第1个键与第2个键(开始重复按键)之间的延时
//rep[1]此后重复按键之前的延时时间,直到按键抬起
//通俗解释就是,假如我按了一个“a”,并且一直按着,那么在显示出来的第一个a与第二个a之间的时间延时为rep[0],而此后的相邻两个a之间的延时为rep[1]
unsignedlong key[NBITS(KEY_MAX)];
unsignedlong led[NBITS(LED_MAX)];
unsignedlong snd[NBITS(SND_MAX)];
//不知道有什么用
intabsmax[ABS_MAX + 1];
intabsmin[ABS_MAX + 1];
intabsfuzz[ABS_MAX + 1];
intabsflat[ABS_MAX + 1];
//显然与绝对坐标值有关,但不知道具体作用
int(*open)(struct input_dev *dev);
void(*close)(struct input_dev *dev);
int(*accept)(struct input_dev *dev, struct file *file);
int(*flush)(struct input_dev *dev, struct file *file);
int(*event)(struct input_dev *dev, unsigned int type, unsigned intcode, int value);
int(*upload_effect)(struct input_dev *dev, struct ff_effect*effect);
int(*erase_effect)(struct input_dev *dev, int effect_id);
//底层与硬件相关的一组操作,若有具体定义,则会在input core层被调用,具体看input.c。
structinput_handle *grab;
//该结构会在后文做具体介绍,这个指针用于占用输入设备用,如键盘
structlist_head h_list;
structlist_head node;
//h_list链表用于与input_handler相联系
//node链表:设备向输入子系统(input subsystem)注册后,会将该链表添加到系统维护的一个链表中去,从而系统可以管理这个设备
0.1:关键结构体input_event信息:
struct input_event {
struct timeval time;
__u16 type;
__u16 code;
__s32 value;
};
type: 设备类型。可以设置为:
#define EV_SYN 0x00 表示设备支持所有的事件
#define EV_KEY 0x01 键盘或者按键,表示一个键码
#define EV_REL 0x02 鼠标设备,表示一个相对的光标位置结果
#define EV_ABS 0x03 手写板产生的值,其是一个绝对整数值
#define EV_MSC 0x04 其他类型
#define EV_LED 0x11 LED灯设备
#define EV_SND 0x12 蜂鸣器,输入声音
#define EV_REP 0x14 允许重复按键类型
#define EV_PWR 0x16 电源管理事件
#define EV_FF_STATUS 0x17
#define EV_MAX 0x1f
#define EV_CNT (EV_MAX+1)
code:根据Type的不同而含义不同。
例如:
Type为EV_KEY时,code表示键盘code或者鼠标Button值。
取值范围:
#define EV_SYN 0x00
到:
#define KEY_MIN_INTERESTING KEY_MUTE
#define KEY_MAX 0x2ff
#define KEY_CNT (KEY_MAX+1)
Type为EV_REL时,code表示操作的是哪个坐标轴,如:REL_X,REL_Y。(因为鼠标有x,y两个轴向,所以一次鼠标移动,会产生两个input_event)
取值范围:
#define REL_X 0x00
#define REL_Y 0x01
#define REL_Z 0x02
#define REL_RX 0x03
#define REL_RY 0x04
#define REL_RZ 0x05
#define REL_HWHEEL 0x06
#define REL_DIAL 0x07
#define REL_WHEEL 0x08
#define REL_MISC 0x09
#define REL_MAX 0x0f
#define REL_CNT (REL_MAX+1)
Type为EV_ABS时,code表示绝对坐标轴向。
value:根据Type的不同而含义不同。
例如:
Type为EV_KEY时,value:0表示按键抬起。1表示按键按下。(4表示持续按下等?)。
Type为EV_REL时,value: 表明移动的值和方向(正负值)。
Type为EV_ABS时,code表示绝对位置。
0.2: Device ID 结构体信息:
struct input_id {
__u16 bustype;
__u16 vendor;
__u16 product;
__u16 version;
};
bustype:
一些枚举类型。如 USB, PCI等。
取值范围:
#defineBUS_PCI 0x01
#define BUS_ISAPNP 0x02
#define BUS_USB 0x03
#define BUS_HIL 0x04
#define BUS_BLUETOOTH 0x05
#define BUS_VIRTUAL 0x06
#define BUS_ISA 0x10
#define BUS_I8042 0x11
#define BUS_XTKBD 0x12
#define BUS_RS232 0x13
#define BUS_GAMEPORT 0x14
#define BUS_PARPORT 0x15
#define BUS_AMIGA 0x16
#define BUS_ADB 0x17
#define BUS_I2C 0x18
#define BUS_HOST 0x19
#define BUS_GSC 0x1A
#define BUS_ATARI 0x1B
#define BUS_SPI 0x1C
vendor,product,version: 厂商号,产品号,版本号。
1.各类ioctl:
1.1:得到Driver Version:
#define EVIOCGVERSION _IOR('E', 0x01, int)
int暗示了ioctl()参数三能够得到int值。
例:
vesion = 0;
ioctl(fd, EVIOCGVERSION, &vesion);
printf("\nDriver Version:[0x%x]\n", vesion);
1.2:得到Device ID:
#define EVIOCGID _IOR('E', 0x02, struct input_id)
从structinput_id暗示,ioctl参数三可以得到此结构体内容。
// 2. Device ID.
memset(&Device_ID, 0, sizeof(structinput_id));
ioctl(fd, EVIOCGID, &Device_ID);
printf("\nbustype:[%d]. vendor:[%d]. product:[%d].version:[%d]\n", Device_ID.bustype, Device_ID.vendor,Device_ID.product, Device_ID.version);
1.3:得到和设置Repeat速度:
#define EVIOCGREP _IOR('E', 0x03, unsigned int[2])
#define EVIOCSREP _IOW('E', 0x03, unsigned int[2])
从unsigned int[2]暗示,ioctl的第三个参数是个数组。
int rep[2];
ioctl(fd, EVIOCGREP, rep);
printf("[0]= %d, [1] = %d\n", rep[0], rep[1]);
注意,其中一些Device不支持Get SetRepeat。此时,Ioctl会报错。
另:参数说明: rep[0]表示在按键重复出现之前 delay的时间; rep[1]表示按键重复出现的时间间隔。
1.4:得到ScanKey和KeyMap。
这个功能Sam没有测试过。所以不具体讨论。
#define EVIOCGKEYCODE _IOR('E', 0x04, unsigned int[2])
#define EVIOCSKEYCODE _IOW('E', 0x04, unsigned int[2])
1.5:得到DeviceName:
#define EVIOCGNAME(len) _IOC(_IOC_READ, 'E', 0x06,len)
此处暗示ioctl参数二:EVIOCGNAME(len)
char name[256]= "Unknown";
ioctl(fd, EVIOCGNAME(sizeof(name)), name);
printf("\nDevice Name:[%s]. \n", name);
1.6:得到设备物理位置:
#define EVIOCGPHYS(len) _IOC(_IOC_READ, 'E', 0x07, len) //getphysical location
此处暗示参数二为:EVIOCGPHYS(len)
尽管设备身份信息和名字信息通常很有用,但是它也许并没有提供足够的信息告诉你当前在使用哪个设备。例如,你当前有两个完全相同的遥控杆,你需要确定每个使用哪个端口。这通常属于拓扑信息( topologyinformation),可以使用 EVIOCGPHYSioctl获取:
charphysic[256]= "Unknown";
if(ioctl(fd, EVIOCGPHYS(sizeof(physic)), physic)< 0)
{
perror("EVIOCGPHYS ioctl");
}
else
printf("Phys location is %s\n", physic);
结果通常为:
Phys location is: usb-hiusb-ehci-2.1/input1
Phys location is: usb-hiusb-ehci-2.1/input2
涵义: Usb部分意味着这使用 usb系统的一个物理拓扑。 2.1表示了从 roothub到 device的路径,这里表示上行 hub接在 roothub的第 2个端口上,设备接在上行 hub的第 1个端口上。 Input0表示这是设备的第 1个eventdevice 节点。
1.7: 得到唯一的ID:
#define EVIOCGUNIQ(len) _IOC(_IOC_READ, 'E', 0x08, len) //getunique identifier
此处暗示ioctl()参数二:EVIOCGUNIQ(len)
char uniq[256]= "Unknown";
if(ioctl(fd, EVIOCGUNIQ(sizeof(uniq)), uniq) <0)
{
perror("EVIOCGUNIQ ioctl");
}
else
printf("UID is %s\n", uniq);
绝大多数设备没有这样的唯一号,所以你使用该 ioctl将返回一个空字符串
1.8:得到全局key/button状态,看其是否被按下或释放:
#defineEVIOCGKEY(len) _IOC(_IOC_READ, 'E', 0x18, len)
此处暗示ioctl()参数二是:EVIOCGKEY(len)
通过这个ioctl, 参数三中得到信息。它在 bitarray里设置了每个 key/button是否被释放。
1.9: 得到LED状态:
#defineEVIOCGLED(len) _IOC(_IOC_READ, 'E', 0x19, len)
LED排列如下:
#define LED_NUML 0x00
#define LED_CAPSL 0x01
#define LED_SCROLLL 0x02
#define LED_COMPOSE 0x03
#define LED_KANA 0x04
#define LED_SLEEP 0x05
#define LED_SUSPEND 0x06
#define LED_MUTE 0x07
#define LED_MISC 0x08
#define LED_MAIL 0x09
#define LED_CHARGING 0x0a
#define LED_MAX 0x0f
#define LED_CNT (LED_MAX+1)
1.10:得到Device能力集:
使用 EVIOCGBITioctl可以获取设备的能力和特性。它告知你设备是否有 key或者 button。
EVIOCGBIT ioctl处理 4个参数( ioctl(fd, EVIOCGBIT(ev_type, max_bytes),bitfield))。 ev_type是返回的 typefeature( 0是个特殊 case,表示返回设备支持的所有的typefeatures)。 max_bytes表示返回的最大字节数。 bitfield域是指向保存结果的内存指针。 returnvalue表示保存结果的实际字节数,如果调用失败,则返回负值。
//找到addr中的对应bit.看其是否为1。
static inttest_bit(int nr, const volatile unsigned long *addr)
{
return 1UL& (addr[BIT_WORD(nr)]>> (nr &(BITS_PER_LONG-1)));
}
memset(pEvtype, 0,sizeof(pEvtype));
if (ioctl(fd,EVIOCGBIT(0, EV_MAX), pEvtype) <0)
{
//printf();
}
for (yalv = 0; yalv< EV_MAX; yalv++)
{
if (test_bit(yalv,pEvtype))
{
printf(" Event type0xx ", yalv);
switch ( yalv)
{
case EV_SYN :
printf(" (SynchEvents)\n");
break;
case EV_KEY :
printf(" (Keys orButtons)\n");
break;
case EV_REL :
printf(" (RelativeAxes)\n");
break;
case EV_ABS :
printf(" (AbsoluteAxes)\n");
break;
case EV_MSC :
printf("(Miscellaneous)\n");
break;
case EV_LED :
printf("(LEDs)\n");
break;
case EV_SND :
printf("(Sounds)\n");
break;
case EV_REP :
printf("(Repeat)\n");
break;
case EV_FF :
caseEV_FF_STATUS:
printf(" (ForceFeedback)\n");
break;
case EV_PWR:
printf(" (PowerManagement)\n");
break;
default:
printf(" (Unknown:0xhx)\n",yalv);
}
}
}
通过这个办法,就可以的到能力集。例如:
Event type 0x00 (Synch Events)
Event type 0x01 (Keys orButtons)
Event type 0x02 (RelativeAxes)
头文件:include/linux/input.h
成员说明:
void*private;
//私有数据指针
char*name;
//设备名字,如键盘名字。
char*phys;
//设备文件节点名,如input/kbd0。
char*uniq;
//全球唯一的ID号。
struct input_id id; /*其他信息,如版本号*/
unsignedlong evbit[NBITS(EV_MAX);]
//该设备驱动所能支持的事件。
//EV_SYN 同步事件
//EV_KEY 键盘事件
//EV_REL 相对坐标事件,用于鼠标
//EV_ABS 绝对坐标事件,用于摇杆
//EV_MSC 其他事件
//EV_LED LED灯事件
//EV_SND 声音事件
//EV_REP 重复按键事件
//EV_FF 受力事件
//EV_PWR 电源事件
//EV_FF_STATUS 受力状态事件
unsignedlong keybit[NBITS(KEY_MAX)];
//键值存放表
unsignedlong relbit[NBITS(REL_MAX)];
//用于存放相对坐标值等
unsignedlong absbit[NBITS(ABS_MAX)];
//用于存放绝对坐标值等
unsignedlong mscbit[NBITS(MSC_MAX)];
//存放其他事件类型
unsignedlong ledbit[NBITS(LED_MAX)];
//存放表示各种状态的LED值
unsignedlong sndbit[NBITS(SND_MAX)];
//存放各种事件的声音
unsignedlong ffbit[NBITS(FF_MAX)];
//存放受力设备的属性
intff_effects_max;
//显然与受力效果有关,具体作用还不大清楚。
unsignedint keycodemax;
unsignedint keycodesize;
void *keycode;
//这三个不是很清楚,有点模糊理解。
unsignedint repeat_key;
//存放重复按键时的键值
structtimer_list timer;
//定时器
structpm_dev *pm_dev;
//考虑到有些设备可能有电源管理
structpt_regs *regs;
//不清楚
intstate;
//显然是表示一个状态,但不清楚具体是谁的状态
intsync;
//具体用于什么也不大清楚
intabs[ABS_MAX + 1];
//显然是与绝对坐标有关的,但具体的作用不清楚。
intrep[REP_MAX + 1];
//存放重复按键时的延时,系统依靠这个延时时间来判断重复按键
//rep[0]表示开始要重复按键时的延时时间,即第1个键与第2个键(开始重复按键)之间的延时
//rep[1]此后重复按键之前的延时时间,直到按键抬起
//通俗解释就是,假如我按了一个“a”,并且一直按着,那么在显示出来的第一个a与第二个a之间的时间延时为rep[0],而此后的相邻两个a之间的延时为rep[1]
unsignedlong key[NBITS(KEY_MAX)];
unsignedlong led[NBITS(LED_MAX)];
unsignedlong snd[NBITS(SND_MAX)];
//不知道有什么用
intabsmax[ABS_MAX + 1];
intabsmin[ABS_MAX + 1];
intabsfuzz[ABS_MAX + 1];
intabsflat[ABS_MAX + 1];
//显然与绝对坐标值有关,但不知道具体作用
int(*open)(struct input_dev *dev);
void(*close)(struct input_dev *dev);
int(*accept)(struct input_dev *dev, struct file *file);
int(*flush)(struct input_dev *dev, struct file *file);
int(*event)(struct input_dev *dev, unsigned int type, unsigned intcode, int value);
int(*upload_effect)(struct input_dev *dev, struct ff_effect*effect);
int(*erase_effect)(struct input_dev *dev, int effect_id);
//底层与硬件相关的一组操作,若有具体定义,则会在input core层被调用,具体看input.c。
structinput_handle *grab;
//该结构会在后文做具体介绍,这个指针用于占用输入设备用,如键盘
structlist_head h_list;
structlist_head node;
//h_list链表用于与input_handler相联系
//node链表:设备向输入子系统(input subsystem)注册后,会将该链表添加到系统维护的一个链表中去,从而系统可以管理这个设备
0.1:关键结构体input_event信息:
struct input_event {
struct timeval time;
__u16 type;
__u16 code;
__s32 value;
};
type: 设备类型。可以设置为:
#define EV_SYN 0x00 表示设备支持所有的事件
#define EV_KEY 0x01 键盘或者按键,表示一个键码
#define EV_REL 0x02 鼠标设备,表示一个相对的光标位置结果
#define EV_ABS 0x03 手写板产生的值,其是一个绝对整数值
#define EV_MSC 0x04 其他类型
#define EV_LED 0x11 LED灯设备
#define EV_SND 0x12 蜂鸣器,输入声音
#define EV_REP 0x14 允许重复按键类型
#define EV_PWR 0x16 电源管理事件
#define EV_FF_STATUS 0x17
#define EV_MAX 0x1f
#define EV_CNT (EV_MAX+1)
code:根据Type的不同而含义不同。
例如:
Type为EV_KEY时,code表示键盘code或者鼠标Button值。
取值范围:
#define EV_SYN 0x00
到:
#define KEY_MIN_INTERESTING KEY_MUTE
#define KEY_MAX 0x2ff
#define KEY_CNT (KEY_MAX+1)
Type为EV_REL时,code表示操作的是哪个坐标轴,如:REL_X,REL_Y。(因为鼠标有x,y两个轴向,所以一次鼠标移动,会产生两个input_event)
取值范围:
#define REL_X 0x00
#define REL_Y 0x01
#define REL_Z 0x02
#define REL_RX 0x03
#define REL_RY 0x04
#define REL_RZ 0x05
#define REL_HWHEEL 0x06
#define REL_DIAL 0x07
#define REL_WHEEL 0x08
#define REL_MISC 0x09
#define REL_MAX 0x0f
#define REL_CNT (REL_MAX+1)
Type为EV_ABS时,code表示绝对坐标轴向。
value:根据Type的不同而含义不同。
例如:
Type为EV_KEY时,value:0表示按键抬起。1表示按键按下。(4表示持续按下等?)。
Type为EV_REL时,value: 表明移动的值和方向(正负值)。
Type为EV_ABS时,code表示绝对位置。
0.2: Device ID 结构体信息:
struct input_id {
__u16 bustype;
__u16 vendor;
__u16 product;
__u16 version;
};
bustype:
一些枚举类型。如 USB, PCI等。
取值范围:
#defineBUS_PCI 0x01
#define BUS_ISAPNP 0x02
#define BUS_USB 0x03
#define BUS_HIL 0x04
#define BUS_BLUETOOTH 0x05
#define BUS_VIRTUAL 0x06
#define BUS_ISA 0x10
#define BUS_I8042 0x11
#define BUS_XTKBD 0x12
#define BUS_RS232 0x13
#define BUS_GAMEPORT 0x14
#define BUS_PARPORT 0x15
#define BUS_AMIGA 0x16
#define BUS_ADB 0x17
#define BUS_I2C 0x18
#define BUS_HOST 0x19
#define BUS_GSC 0x1A
#define BUS_ATARI 0x1B
#define BUS_SPI 0x1C
vendor,product,version: 厂商号,产品号,版本号。
1.各类ioctl:
1.1:得到Driver Version:
#define EVIOCGVERSION _IOR('E', 0x01, int)
int暗示了ioctl()参数三能够得到int值。
例:
vesion = 0;
ioctl(fd, EVIOCGVERSION, &vesion);
printf("\nDriver Version:[0x%x]\n", vesion);
1.2:得到Device ID:
#define EVIOCGID _IOR('E', 0x02, struct input_id)
从structinput_id暗示,ioctl参数三可以得到此结构体内容。
// 2. Device ID.
memset(&Device_ID, 0, sizeof(structinput_id));
ioctl(fd, EVIOCGID, &Device_ID);
printf("\nbustype:[%d]. vendor:[%d]. product:[%d].version:[%d]\n", Device_ID.bustype, Device_ID.vendor,Device_ID.product, Device_ID.version);
1.3:得到和设置Repeat速度:
#define EVIOCGREP _IOR('E', 0x03, unsigned int[2])
#define EVIOCSREP _IOW('E', 0x03, unsigned int[2])
从unsigned int[2]暗示,ioctl的第三个参数是个数组。
int rep[2];
ioctl(fd, EVIOCGREP, rep);
printf("[0]= %d, [1] = %d\n", rep[0], rep[1]);
注意,其中一些Device不支持Get SetRepeat。此时,Ioctl会报错。
另:参数说明: rep[0]表示在按键重复出现之前 delay的时间; rep[1]表示按键重复出现的时间间隔。
1.4:得到ScanKey和KeyMap。
这个功能Sam没有测试过。所以不具体讨论。
#define EVIOCGKEYCODE _IOR('E', 0x04, unsigned int[2])
#define EVIOCSKEYCODE _IOW('E', 0x04, unsigned int[2])
1.5:得到DeviceName:
#define EVIOCGNAME(len) _IOC(_IOC_READ, 'E', 0x06,len)
此处暗示ioctl参数二:EVIOCGNAME(len)
char name[256]= "Unknown";
ioctl(fd, EVIOCGNAME(sizeof(name)), name);
printf("\nDevice Name:[%s]. \n", name);
1.6:得到设备物理位置:
#define EVIOCGPHYS(len) _IOC(_IOC_READ, 'E', 0x07, len) //getphysical location
此处暗示参数二为:EVIOCGPHYS(len)
尽管设备身份信息和名字信息通常很有用,但是它也许并没有提供足够的信息告诉你当前在使用哪个设备。例如,你当前有两个完全相同的遥控杆,你需要确定每个使用哪个端口。这通常属于拓扑信息( topologyinformation),可以使用 EVIOCGPHYSioctl获取:
charphysic[256]= "Unknown";
if(ioctl(fd, EVIOCGPHYS(sizeof(physic)), physic)< 0)
{
perror("EVIOCGPHYS ioctl");
}
else
printf("Phys location is %s\n", physic);
结果通常为:
Phys location is: usb-hiusb-ehci-2.1/input1
Phys location is: usb-hiusb-ehci-2.1/input2
涵义: Usb部分意味着这使用 usb系统的一个物理拓扑。 2.1表示了从 roothub到 device的路径,这里表示上行 hub接在 roothub的第 2个端口上,设备接在上行 hub的第 1个端口上。 Input0表示这是设备的第 1个eventdevice 节点。
1.7: 得到唯一的ID:
#define EVIOCGUNIQ(len) _IOC(_IOC_READ, 'E', 0x08, len) //getunique identifier
此处暗示ioctl()参数二:EVIOCGUNIQ(len)
char uniq[256]= "Unknown";
if(ioctl(fd, EVIOCGUNIQ(sizeof(uniq)), uniq) <0)
{
perror("EVIOCGUNIQ ioctl");
}
else
printf("UID is %s\n", uniq);
绝大多数设备没有这样的唯一号,所以你使用该 ioctl将返回一个空字符串
1.8:得到全局key/button状态,看其是否被按下或释放:
#defineEVIOCGKEY(len) _IOC(_IOC_READ, 'E', 0x18, len)
此处暗示ioctl()参数二是:EVIOCGKEY(len)
通过这个ioctl, 参数三中得到信息。它在 bitarray里设置了每个 key/button是否被释放。
1.9: 得到LED状态:
#defineEVIOCGLED(len) _IOC(_IOC_READ, 'E', 0x19, len)
LED排列如下:
#define LED_NUML 0x00
#define LED_CAPSL 0x01
#define LED_SCROLLL 0x02
#define LED_COMPOSE 0x03
#define LED_KANA 0x04
#define LED_SLEEP 0x05
#define LED_SUSPEND 0x06
#define LED_MUTE 0x07
#define LED_MISC 0x08
#define LED_MAIL 0x09
#define LED_CHARGING 0x0a
#define LED_MAX 0x0f
#define LED_CNT (LED_MAX+1)
1.10:得到Device能力集:
使用 EVIOCGBITioctl可以获取设备的能力和特性。它告知你设备是否有 key或者 button。
EVIOCGBIT ioctl处理 4个参数( ioctl(fd, EVIOCGBIT(ev_type, max_bytes),bitfield))。 ev_type是返回的 typefeature( 0是个特殊 case,表示返回设备支持的所有的typefeatures)。 max_bytes表示返回的最大字节数。 bitfield域是指向保存结果的内存指针。 returnvalue表示保存结果的实际字节数,如果调用失败,则返回负值。
//找到addr中的对应bit.看其是否为1。
static inttest_bit(int nr, const volatile unsigned long *addr)
{
return 1UL& (addr[BIT_WORD(nr)]>> (nr &(BITS_PER_LONG-1)));
}
memset(pEvtype, 0,sizeof(pEvtype));
if (ioctl(fd,EVIOCGBIT(0, EV_MAX), pEvtype) <0)
{
//printf();
}
for (yalv = 0; yalv< EV_MAX; yalv++)
{
if (test_bit(yalv,pEvtype))
{
printf(" Event type0xx ", yalv);
switch ( yalv)
{
case EV_SYN :
printf(" (SynchEvents)\n");
break;
case EV_KEY :
printf(" (Keys orButtons)\n");
break;
case EV_REL :
printf(" (RelativeAxes)\n");
break;
case EV_ABS :
printf(" (AbsoluteAxes)\n");
break;
case EV_MSC :
printf("(Miscellaneous)\n");
break;
case EV_LED :
printf("(LEDs)\n");
break;
case EV_SND :
printf("(Sounds)\n");
break;
case EV_REP :
printf("(Repeat)\n");
break;
case EV_FF :
caseEV_FF_STATUS:
printf(" (ForceFeedback)\n");
break;
case EV_PWR:
printf(" (PowerManagement)\n");
break;
default:
printf(" (Unknown:0xhx)\n",yalv);
}
}
}
通过这个办法,就可以的到能力集。例如:
Event type 0x00 (Synch Events)
Event type 0x01 (Keys orButtons)
Event type 0x02 (RelativeAxes)
相关文章推荐
- 设计模式--组合模式
- NSDatepicker
- iOS程序支持64位以及project.pbxproj文件的介绍
- socket长连接所用到的八大技术
- Thinkphp 3.2命名空间版如何使用PHPExcel导入Excel文件
- POJ3278.Catch That Cow
- 【POJ3270】【Cow Sorting】
- 利用jaxb进行xml与javabean的数据绑定
- Linux命令学习之二
- HDOJ 2087 剪花布条 (KMP简单题)
- 虚拟内存
- hdu1698
- 缩放位图以及简单的图形处理
- 一起talk C栗子吧(第三十二回:C语言实例--再谈最大公约数)
- 所闻所获4:下拉刷新控件2
- 猴子选大王
- linux syetem()函数
- POJ 2718
- Java集合类中Sort排序的使用方法
- android DDMS 导出files文件夹下的容时报错