Re: [PATCH 0/3] hid: Enable report fixup on rebind

From: Nikolai Kondrashov
Date: Sun May 06 2012 - 12:52:29 EST


Hi Jiri, Henrik,

On 04/23/2012 12:27 AM, Jiri Kosina wrote:
On Sun, 22 Apr 2012, Henrik Rydberg wrote:

This patchset contains a resolution to the problem with
driver-specific modification of the report descriptor. The core of the
problem lies with the dual semantics of hid_parse_report(), which is
therefore split into two functions. As a consequence, the hid core can
handle the rebind case internally, with no changes to the
drivers. Out-of-tree drivers will work fine as long as they operate in
the same way as the in-kernel drivers.

The first two patches are bug fixes found in the process. I am hoping
for some test feedback on those. The third patch is the main one.

Hi Henrik,

thanks a lot for looking into this. I will look into the patches in more
detail tomorrow. I am now just adding Nikolai to CC, as he was the first
one to bring this up and actually has a driver that exposed the fact that
just freeing/reinstatiating rdesc is not enough.

I've managed to throw together a script which rebinds a device to a specific
out-of-tree HID driver automatically. Please find it attached. I'll be
bundling it with the modules, probably.

I'm planning to use it with udev rules looking like this one:

SUBSYSTEM=="hid", ACTION=="add", ENV{HID_ID}=="0003:0000172F:*", \
RUN+="/usr/local/bin/digimend-rebind"

So, the out-of-tree HID module problem is finally solved, at least for my
current uses. Thanks a lot!

Sincerely,
Nick
#!/bin/sh
#
# DIGImend specific driver rebinding script. To be invoked by udev.
# Author: Nikolai Kondrashov <spbnick@xxxxxxxxx>
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#

# Write a string to a file, ignoring ENODEV.
write_ignore_enodev() {
local str="$1"
local path="$2"
local output=""

# Write the string with tee, capturing error output
if ! output="`(echo \"$str\" | tee \"$path\" >/dev/null) 2>&1`"; then
# Raise anything except ENODEV
if [ "${output##*: }" != "No such device" ]; then
echo "$output" >&2
return 1
fi
fi
}

(
set -e -u

progname="`basename \"$0\"`"

id="`basename $DEVPATH`"

current_driver_path="`readlink -v -f /sys${DEVPATH}/driver`"
if [ -e "$current_driver_path" ]; then
current_driver="`basename \"$current_driver_path\"`"
else
current_driver=""
fi

specific_module="`modprobe -R $MODALIAS`"

# Assume the driver would be called the same as module,
# but without the "hid_" or "hid-" prefix
specific_driver="${specific_module#hid[_-]}"
specific_driver_path="/sys/bus/hid/drivers/$specific_driver"

if [ "$current_driver" != "$specific_driver" ]; then
logger -p daemon.notice -t "$progname" "rebinding $DEVPATH"

# Ensure the specific driver module is loaded
modprobe "$specific_module"

# Unbind from the current driver, if any
if [ -n "$current_driver" ]; then
write_ignore_enodev "$id" "$current_driver_path/unbind"
fi

# Bind to the specific driver
write_ignore_enodev "$id" "$specific_driver_path/bind"
fi
) 2>&1 | logger -p daemon.warning -t "$progname"