博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Mouse Key Hook
阅读量:6425 次
发布时间:2019-06-23

本文共 6523 字,大约阅读时间需要 21 分钟。

http://www.linuxjournal.com/article/6429

 

No matter how many buttons an input device has or how many kinds of events it can generate, you can now work with it from user space.

In last month's article, we saw how the Linux input subsystem worked inside the kernel, ending with a quick mention of the event handlers. Each handler essentially provides a different user-space API, converting input events into the particular format that makes up that API.

One of the key aspects of the input subsystem integration into Linux is the availability of the event interface. This basically exposes the raw events to userspace through a collection of character device nodes—one character device node per logical input device. The event interface is a really powerful technique, because it allows the manipulation of the events in userspace without information loss. For example, legacy mouse interfaces support only two relative axes and up to five buttons. These are normally mapped to the two real axes and three real buttons, with the fourth and fifth buttons logically being mapped to the scroll wheel up and scroll wheel down events.

However, this mapping becomes a problem when trying to use a mouse with a scroll wheel and more than three buttons, because any additional buttons can be mapped only to an existing button. The legacy APIs also impede use of advanced input devices, such as space balls and other devices' with many axes. By contrast, the event API provides full access to the devices capabilities, and it even includes a per-device description of those capabilities and other device characteristics.

This month's article focuses on the various ioctl capabilities of the event interface, in addition to the normal read and write calls.

Finding the Version of the Event Interface

The event interface supports determining the version of the event device code, using the EVIOCGVERSION ioctl function. The argument is an int (32 bits) and is meant to be interpreted as a major version (two high bytes), a minor version (third byte) and a patch level (low byte). The same value is returned from each event device on a machine.

An example of the EVIOCGVERSION is shown in Listing 1. The first argument to the ioctl function is an open file descriptor for the event device node (for example, /dev/input/event0). Notice that you have to pass a pointer to the integer variable, not the variable itself, as the third argument to the ioctl call.

Finding Information about the Device's Identity

The event interface supports retrieving information associated with the underlying device using the EVIOCGID ioctl. The argument is a pointer to an input_id structure; the input_id structure is defined as shown in Listing 2. The __u16 data type is a Linux-specific, unsigned 16-bit integer. You can safely cast it to a standard uint16_t in your code.

The bus type is the only field that contains accurate data. You should probably consider it to be an opaque, enumerated type, and compare it with the various BUS_x type definitions provided in <linux/input.h>. The vendor, product and version fields are bus type-specific information relating to the identity of the device. Modern devices (typically using PCI or USB) do have information that can be used, but legacy devices (such as serial mice, PS/2 keyboards and game ports on ISA sound cards) do not. These numbers therefore are not meaningful for some values of bus type.

An example of the EVIOCGID ioctl is shown in Listing 3. This example calls the ioctl and then prints out the results. The case logic shows all current bus types. Here is an example of running that code: vendor 045e product 001d version 0111 is on a Universal Serial Bus.

In addition to the type of bus and the vendor, product and version information, some devices can provide strings that make up meaningful names. This can be obtained from the event interface using the EVIOCGNAME ioctl. This ioctl provides a string and returns the length of the string (or a negative error value). If the string is too long to fit into the argument, it will be truncated. An example is provided in Listing 4. If it seems strange that the argument is not &name, remember the name of an array is the same as a pointer to the first element. Therefore, &name would be a pointer to a pointer to the first element, which is not what we want. If you really want to use a dereference, use &(name[0]).

Here is an example of running that event code:

The device on /dev/input/event0 says its name    is Logitech USB-PS/2 Optical Mouse

Not all devices contain meaningful names, however, so kernel input drivers try to provide something meaningful. For example, USB devices without manufacturer or product strings concatenate the vendor and product ID information.

Although device identity and name information is often useful, it may not be sufficient information to tell which device you have. For example, if you have two joysticks that are the same, you may need to identify them based on which port they use. This is usually known as topology information, and you can get this from the event interface using the EVIOCGPHYS ioctl. Like EVIOCGNAME, this provides a string and returns the length of the string (or a negative error number). An example is shown in Listing 5; running that example will produce something like:

The device on /dev/input/event0 says its path    is usb-00:01.2-2.1/input0

To understand what this string is showing, you need to break it down into parts. The usb part means this is a physical topology from the USB system. The 00:01.2 is the PCI bus information for the USB host controller (in this case, bus 0, slot 1, function 2). The 2.1 shows the path from the root hub to the device. In this case, the upstream hub is plugged in to the second port on the root hub, and that device is plugged in to the first port on the upstream hub. input0 means this is the first event device on the device. Most devices have only one, but multimedia keyboards may present the normal keyboard on one interface and the multimedia function keys on a second interface. This topology example is shown in Figure 1.

Figure 1. Keyboard Topology

This setup doesn't help if you swap the cables on two identical devices. The only thing that can help in this case is if the device has some form of unique identifier, such as a serial number. You can get this information using the EVIOCGUNIQ ioctl. An example is shown in Listing 6. Most devices don't have such an identifier, and you will get an empty string from this ioctl.

转载地址:http://ajyga.baihongyu.com/

你可能感兴趣的文章
oracle kill所有plsql developer进程
查看>>
python实现登录查询(可以模糊查询)
查看>>
LAMP架构(apache用户认证,域名重定向,apache访问日志)
查看>>
struts2.0的json操作
查看>>
SQL注入神器——sqlmap
查看>>
Unity导航 (寻路系统Nav Mesh Agent)
查看>>
SaltStack配置语法-YAML和Jinja
查看>>
运用免费OA让你有意想不到的效果
查看>>
一些软件设计软则
查看>>
Linux运维基础命令
查看>>
使用PowerShell配置IP地址
查看>>
第十一章 MySQL运算符
查看>>
JAVA常见算法题(十七)
查看>>
GUI鼠标相关设置
查看>>
使用 <Iframe>实现跨域通信
查看>>
闭包--循序学习
查看>>
项目实战之集成邮件开发
查看>>
解决C3P0在Linux下Failed to get local InetAddress for VMID问题
查看>>
1531 山峰 【栈的应用】
查看>>
巧用美女照做微信吸粉,你会做吗?
查看>>