Commit a025a18f authored by Hans de Goede's avatar Hans de Goede Committed by Benjamin Tissoires

HID: core: Call request_module before doing device_add

Recent kernels allow the generic-hid driver to be used as fallback for
devices with a specialized driver, when the hiddev is not listed in
hid_have_special_driver. Over time we are removing more and more
devices from the hid_have_special_driver table as devices get tested
to support this setup.

Before this commit the following happens when a HID device which has a
special-driver and is no longer listed in hid_have_special_driver, gets
enumerated:

1) device_add() gets called
2) bus_add_device() looks for a matching already registered hid driver,
   and bind hid-generic to the new device
3) kobject_uevent(&dev->kobj, KOBJ_ADD) gets called notifying userspace of
   the new hid_dev. udev calls modprobe based on the modalias in the uevent
4) The special driver gets loaded by modprobe
5) __hid_bus_reprobe_drivers() unbinds hid-generic and binds the new driver

There are a couple of downsides to this:

a) The probing messages printend when a HID driver bounds show up twice in
dmesg, which is confusing for the user

b) The (un)binding typically causes one or more evdev device-nodes to get
(un)registered firing of udev events to which e.g. the xserver responds by
(un)registering xinput devices and reporting this to interested clients.
IOW the i. bind generic, ii. unbind generic, iii. bind special driver dance
sets in motion a whole chain of events each step, while we really only want
the events from step iii. to be reported to userspace.

This commits introduces a request_module call before the device_add()
call, so that the special-driver is loaded when step 2) looks for a
matching driver and we directly bind the specialized driver.

Note the request_module call translates to an execve("/sbin/modprobe", ...)
and we now do this for each HID device added. So this is not entirely free,
but adding HID devices is not something which happens 100s of times a
second, so this should be fine.
Signed-off-by: default avatarHans de Goede <hdegoede@redhat.com>
[bentiss: fixed typo in commit message found by checkpatch.pl]
Signed-off-by: default avatarBenjamin Tissoires <benjamin.tissoires@redhat.com>
parent 58e75155
...@@ -2361,6 +2361,14 @@ int hid_add_device(struct hid_device *hdev) ...@@ -2361,6 +2361,14 @@ int hid_add_device(struct hid_device *hdev)
dev_set_name(&hdev->dev, "%04X:%04X:%04X.%04X", hdev->bus, dev_set_name(&hdev->dev, "%04X:%04X:%04X.%04X", hdev->bus,
hdev->vendor, hdev->product, atomic_inc_return(&id)); hdev->vendor, hdev->product, atomic_inc_return(&id));
/*
* Try loading the module for the device before the add, so that we do
* not first have hid-generic binding only to have it replaced
* immediately afterwards with a specialized driver.
*/
request_module("hid:b%04Xg%04Xv%08Xp%08X",
hdev->bus, hdev->group, hdev->vendor, hdev->product);
hid_debug_register(hdev, dev_name(&hdev->dev)); hid_debug_register(hdev, dev_name(&hdev->dev));
ret = device_add(&hdev->dev); ret = device_add(&hdev->dev);
if (!ret) if (!ret)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment