#!/bin/sh # # input-specific hotplug policy agent. # # This should handle 2.6.* input hotplugging, # with a consistent framework for adding device and driver # specific handling. # # Normally, adding a input device will modprobe handler(s) for # this device. # # Kernel input hotplug params include (not all of them may be available): # # ACTION=%s [add or remove] # PRODUCT=%x/%x/%x/%x # NAME=%s # PHYS=%s # EV=%lx # KEY=%lx %lx ... # REL=%lx # ABS=%lx %lx ... # MSC=%lx # LED=%lx # SND=%lx # FF=%lx %lx ... # # HISTORY: # # 30-Jul-2003 initial version # debug_mesg () { : } # accumulates list of modules we may care about DRIVERS="" if [ "$ACTION" = "" ]; then mesg Bad INPUT agent invocation, no action exit 1 fi # we can't "unset IFS" on bash1, so save a copy DEFAULT_IFS="$IFS" # # Each modules.inputmap format line corresponds to one entry in a # MODULE_DEVICE_TABLE(input,...) declaration in a kernel file. # matchBits=0; i_bustype=0; i_vendor=0; i_product=0; i_version=0; i_evBits=0 input_join_words () { name="$1" array="$2" if [ "$array" = '' ]; then return fi set $array tmp="$1" shift while [ "$#" -gt 0 ]; do tmp="$tmp:$1" shift done eval "$name=\"$tmp\"" } input_convert_vars () { if [ "$PRODUCT" != "" ]; then IFS=/ set $PRODUCT '' IFS="$DEFAULT_IFS" i_bustype=$((0x$1)) i_vendor=$((0x$2)) i_product=$((0x$3)) i_version=$((0x$4)) fi if [ "$EV" != "" ]; then i_evBits=$((0x$EV)) fi input_join_words i_keyBits "$KEY" input_join_words i_relBits "$REL" input_join_words i_absBits "$ABS" input_join_words i_mscBits "$MSC" input_join_words i_ledBits "$LED" input_join_words i_sndBits "$SND" input_join_words i_ffBits "$FF" } INPUT_DEVICE_ID_MATCH_BUS=1 INPUT_DEVICE_ID_MATCH_VENDOR=2 INPUT_DEVICE_ID_MATCH_PRODUCT=4 INPUT_DEVICE_ID_MATCH_VERSION=8 INPUT_DEVICE_ID_MATCH_EVBIT=$((0x010)) INPUT_DEVICE_ID_MATCH_KEYBIT=$((0x020)) INPUT_DEVICE_ID_MATCH_RELBIT=$((0x040)) INPUT_DEVICE_ID_MATCH_ABSBIT=$((0x080)) INPUT_DEVICE_ID_MATCH_MSCBIT=$((0x100)) INPUT_DEVICE_ID_MATCH_LEDBIT=$((0x200)) INPUT_DEVICE_ID_MATCH_SNDBIT=$((0x400)) INPUT_DEVICE_ID_MATCH_FFBIT=$((0x800)) input_match_bits () { mod_bits=$1 dev_bits=$2 if [ "$dev_bits" = "" ]; then return 0 fi mword=$((0x${mod_bits##*:})) dword=$((0x${dev_bits##*:})) while true; do if [ $(( $mword & $dword != $mword )) -eq 1 ]; then return 1 fi mod_bits=${mod_bits%:*} dev_bits=${dev_bits%:*} case "$mod_bits-$dev_bits" in *:*-*:* ) : continue ;; *:*-*|*-*:* ) return 0 ;; * ) return 1 ;; esac done } # # stdin is "modules.inputmap" syntax # on return, all matching modules were added to $DRIVERS # input_map_modules () { while read line do # comments are lines that start with "#" ... # be careful, they still get parsed by bash! case "$line" in \#*) continue ;; esac set $line module="$1" matchBits=$(($2)) bustype=$(($3)) vendor=$(($4)) product=$(($5)) version=$(($6)) evBits="$7" keyBits="$8" relBits="$9" shift 9 absBits="$1" cbsBits="$2" ledBits="$3" sndBits="$4" ffBits="$5" driverInfo=$(($6)) : checkmatch $module : bustype $bustype $i_bustype if [ $INPUT_DEVICE_ID_MATCH_BUS -eq $(( $matchBits & $INPUT_DEVICE_ID_MATCH_BUS )) ] && [ $bustype -ne $i_bustype ]; then continue fi : vendor $vendor $i_vendor if [ $INPUT_DEVICE_ID_MATCH_VENDOR -eq $(( $matchBits & $INPUT_DEVICE_ID_MATCH_VENDOR )) ] && [ $vendor -ne $i_vendor ]; then continue fi : product $product $i_product if [ $INPUT_DEVICE_ID_MATCH_PRODUCT -eq $(( $matchBits & $INPUT_DEVICE_ID_MATCH_PRODUCT )) ] && [ $product -ne $i_product ]; then continue fi # version i_version $i_version < version $version if [ $INPUT_DEVICE_ID_MATCH_VERSION -eq $(( $matchBits & $INPUT_DEVICE_ID_MATCH_VERSION )) ] && [ $version -ge $i_version ]; then continue fi : evBits $evBits $i_evBits if [ $INPUT_DEVICE_ID_MATCH_EVBIT -eq $(( $matchBits & $INPUT_DEVICE_ID_MATCH_EVBIT )) ] && input_match_bits "$evBits" "$i_evBits"; then continue fi : keyBits $keyBits $i_keyBits if [ $INPUT_DEVICE_ID_MATCH_KEYBIT -eq $(( $matchBits & $INPUT_DEVICE_ID_MATCH_KEYBIT )) ] && input_match_bits "$keyBits" "$i_keyBits"; then continue fi : relBits $relBits $i_relBits if [ $INPUT_DEVICE_ID_MATCH_RELBIT -eq $(( $matchBits & $INPUT_DEVICE_ID_MATCH_RELBIT )) ] && input_match_bits "$relBits" "$i_relBits"; then continue fi : absBits $absBits $i_absBits if [ $INPUT_DEVICE_ID_MATCH_ABSBIT -eq $(( $matchBits & $INPUT_DEVICE_ID_MATCH_ABSBIT )) ] && input_match_bits "$absBits" "$i_absBits"; then continue fi : mscBits $mscBits $i_mscBits if [ $INPUT_DEVICE_ID_MATCH_MSCBIT -eq $(( $matchBits & $INPUT_DEVICE_ID_MATCH_MSCBIT )) ] && input_match_bits "$mscBits" "$i_mscBits"; then continue fi : ledBits $ledBits $_ledBits if [ $INPUT_DEVICE_ID_MATCH_LEDBIT -eq $(( $matchBits & $INPUT_DEVICE_ID_MATCH_LEDBIT )) ] && input_match_bits "$ledBits" "$i_ledBits"; then continue fi : sndBits $sndBits $i_sndBits if [ $INPUT_DEVICE_ID_MATCH_SNDBIT -eq $(( $matchBits & $INPUT_DEVICE_ID_MATCH_SNDBIT )) ] && input_match_bits "$sndBits" "$i_sndBits"; then continue fi : ffBits $ffBits $i_ffBits if [ $INPUT_DEVICE_ID_MATCH_FFBIT -eq $(( $matchBits & $INPUT_DEVICE_ID_MATCH_FFBIT )) ] && input_match_bits "$ffBits" "$i_ffBits"; then continue fi : driverInfo $driverInfo if [ $matchBits -eq 0 ] && [ $driverInfo -eq 0 ]; then continue fi # It was a match! case " $DRIVERS " in *" $module "* ) : already found ;; * ) DRIVERS="$module $DRIVERS" ;; esac : drivers $DRIVERS done } # # What to do with this INPUT hotplug event? # case $ACTION in add) # generated by module-init-tools MAP_CURRENT=/lib/modules/`uname -r`/modules.inputmap if [ -r $MAP_CURRENT ]; then input_convert_vars input_map_modules < $MAP_CURRENT for MODULE in $DRIVERS; do /sbin/modprobe $MODULE [ -x /etc/udev/agents.d/input/$MODULE ] && /etc/udev/agents.d/input/$MODULE done LABEL="INPUT product $PRODUCT" debug_mesg "$LABEL, found drivers: $DRIVERS" fi ;; remove) ;; *) exit 1 ;; esac