linux input子系统的event编号修改
在对接甲方的时候,一些input外设需要固定的input、event编号。而不同厂家不同型号的驱动在内核中加载的顺序不同,因此/dev/input下的event对应的设备不固定,如果更换外设的话event会发生相应的变化,是对接很不方便。
1、查看系统总线上的input设备
# cat /proc/bus/input/devices
I: Bus=0000 Vendor=0000 Product=0000 Version=0000
N: Name="rockchip,rk3308-vad Headphones"
P: Phys=ALSA
S: Sysfs=/devices/platform/vad-acodec-sound/sound/card0/input0
U: Uniq=
H: Handlers=event0
B: PROP=0
B: EV=21
B: SW=4
I: Bus=0019 Vendor=0001 Product=0001 Version=0100
N: Name="adc-keys"
P: Phys=adc-keys/input0
S: Sysfs=/devices/platform/adc-keys/input/input1
U: Uniq=
H: Handlers=event1 cpufreq
B: PROP=0
B: EV=3
B: KEY=200000 0 0 0 1000000 8000 0 0 c0000 0 0 0
I: Bus=0019 Vendor=0001 Product=0001 Version=0100
N: Name="test_key"
P: Phys=gpio-keys/input0
S: Sysfs=/devices/platform/cdn_key/input/input3
U: Uniq=
H: Handlers=event2 cpufreq
B: PROP=0
B: EV=100003
B: KEY=40 0 0 0
2、源码路径
input子系统的源码:kernel/drivers/input/input.c、kernel/drivers/input/evdev.c
3、修改input编号
根据源码可找到input_allocate_device函数,新的输入设备通过此函数分配内存,同时确定input编号,如下:
/**
* input_allocate_device - allocate memory for new input device
*
* Returns prepared struct input_dev or %NULL.
*
* NOTE: Use input_free_device() to free devices that have not been
* registered; input_unregister_device() should be used for already
* registered devices.
*/
struct input_dev *input_allocate_device(void)
{
static atomic_t input_no = ATOMIC_INIT(-1);
struct input_dev *dev;
dev = kzalloc(sizeof(struct input_dev), GFP_KERNEL);
if (dev) {
dev->dev.type = &input_dev_type;
dev->dev.class = &input_class;
device_initialize(&dev->dev);
mutex_init(&dev->mutex);
spin_lock_init(&dev->event_lock);
init_timer(&dev->timer);
INIT_LIST_HEAD(&dev->h_list);
INIT_LIST_HEAD(&dev->node);
dev_set_name(&dev->dev, "input%lu",
(unsigned long)atomic_inc_return(&input_no));
__module_get(THIS_MODULE);
}
return dev;
}
EXPORT_SYMBOL(input_allocate_device);
以test_key为例,将input0修改为input1。
struct input_dev *input_allocate_device(void)
{
static atomic_t input_no = ATOMIC_INIT(-1);
struct input_dev *dev;
dev = kzalloc(sizeof(struct input_dev), GFP_KERNEL);
if (dev) {
dev->dev.type = &input_dev_type;
dev->dev.class = &input_class;
device_initialize(&dev->dev);
mutex_init(&dev->mutex);
spin_lock_init(&dev->event_lock);
init_timer(&dev->timer);
INIT_LIST_HEAD(&dev->h_list);
INIT_LIST_HEAD(&dev->node);
/*dev_set_name(&dev->dev, "input%lu",
(unsigned long)atomic_inc_return(&input_no));*/
if (strcmp(dev->name,"test_key") == 0) {
printk("Ares Debug test_key fixed to input1. \r\n");
dev_set_name(&dev->dev, "input1");
}
else {
unsigned long inputNO = (unsigned long)atomic_inc_return(&input_no);
if(inputNO == 1) {
printk("Ares Debug input1 has registed, turn to next. \r\n");
inputNO = (unsigned long)atomic_inc_return(&input_no)
}
printk("Ares Debug %s fixed to input%d. \r\n",dev->name,inputNO);
dev_set_name(&dev->dev, "input%lu", (unsigned long)inputNO);
}
__module_get(THIS_MODULE);
}
return dev;
}
EXPORT_SYMBOL(input_allocate_device);
4、修改enent编号
根据源码可找到evdev_connect函数,新的输入设备通过此函数确定event编号,如下:
static int evdev_connect(struct input_handler *handler, struct input_dev *dev,
const struct input_device_id *id)
{
struct evdev *evdev;
int minor;
int dev_no;
int error;
minor = input_get_new_minor(EVDEV_MINOR_BASE, EVDEV_MINORS, true);
if (minor < 0) {
error = minor;
pr_err("failed to reserve new minor: %d\n", error);
return error;
}
......
err_cleanup_evdev:
evdev_cleanup(evdev);
err_unregister_handle:
input_unregister_handle(&evdev->handle);
err_free_evdev:
put_device(&evdev->dev);
err_free_minor:
input_free_minor(minor);
return error;
}
以test_key为例,将event2修改为event1。
static int evdev_connect(struct input_handler *handler, struct input_dev *dev,
const struct input_device_id *id)
{
struct evdev *evdev;
int minor;
int dev_no;
int error;
//minor = input_get_new_minor(EVDEV_MINOR_BASE, EVDEV_MINORS, true);
if(strcmp(dev->name, "test_key") == 0) {
printk("evdev_connect: Ares Debug test_key fixed to event0. \r\n");
minor = EVDEV_MINOR_BASE + 1;
}
else {
minor = input_get_new_minor(EVDEV_MINOR_BASE, EVDEV_MINORS, true);
if(minor == EVDEV_MINOR_BASE + 1) {
printk("evdev_connect: Ares Debug event0 has registed. turn to next. \r\n");
minor = input_get_new_minor(EVDEV_MINOR_BASE, EVDEV_MINORS, true);
}
}
printk("evdev_connect: %s: minor = %d \r\n", dev->name, minor);
if (minor < 0) {
error = minor;
pr_err("failed to reserve new minor: %d\n", error);
return error;
}
......
err_cleanup_evdev:
evdev_cleanup(evdev);
err_unregister_handle:
input_unregister_handle(&evdev->handle);
err_free_evdev:
put_device(&evdev->dev);
err_free_minor:
input_free_minor(minor);
return error;
}
注:以上是我的一些记录和遇到的问题,以及解决方法,如果有不对的地方,请各位大佬指出。
1、转载说明:
转载于:https://blog.csdn.net/Auris/article/details/116156047