* sample /sbin/hotplug script
@ 2000-11-28 0:09 David Brownell
0 siblings, 0 replies; only message in thread
From: David Brownell @ 2000-11-28 0:09 UTC (permalink / raw)
To: linux-kernel
[-- Attachment #1: Type: text/plain, Size: 1100 bytes --]
I've been quite pleased to see many recent improvement in hotplug
support ... 2.4 test11 is now hotplugging USB network adapters for
me when I need that! And many other devices at least get their
driver modules autoloaded (using modutils support) even if some
devices still need hand setup before they're usable.
To make a long story short, if you'd like to try it out I strongly
encourage you to put the attached shell script into /sbin/hotplug
and see if it does the right things when you plug in USB devices
or Cardbus adapters into your system. (And configure HOTPLUG;
see its config.help for more information.)
The test11 release has hotplug support for PCI, USB, and also for
networking interfaces. (Though I've not tested the Cardbus/PCI
support myself, and know it can't support class-based driver binding
without a small patch I'll resubmit.)
This script should handle all three. It's a start! Improvements
should be easy enough ... :-)
- Dave
p.s. I'm particularly aware of contributions to the Linux
hotplugging effort from Keith Owens, Adam Richter, and
Jeff Garzik.
[-- Attachment #2: hotplug.sh --]
[-- Type: application/octet-stream, Size: 11904 bytes --]
#!/bin/bash
#
# This is a reference implementation for /sbin/hotplug, which works
# on most GNU/Linux systems without ANY additional software.
#
# This implementation delegates to type-specific agents, such as
# "/etc/hotplug/network.agent", where they exist. Otherwise it
# uses built-in in support for USB and PCI hotplug events, trying
# to load a module that appears to handle this device.
#
# /proc/sys/kernel/hotplug controls the program invoked by the kernel.
# /sbin/hotplug is the default value, which you may change. (A null
# string prevents the kernel from invoking a hotplug program.) To make
# this functionality available, your kernel config must include HOTPLUG
# (and currently KMOD).
#
#
# HISTORY:
#
# 24-Nov-2000 Update matching a test12 prepatch
# 21-Nov-2000 Update for 2.4.0-test11 "net", "pci" support (needs
# another kernel fix for pci/cardbus)
# 06-Nov-2000 Build in support for modules.{usb,pci}map; Cardbus may
# now work, with a kernel patch. /etc/hotplug directory hooks.
# 09-Jul-2000 Initial version; kernel USB hotplugging starts, using
# the existing USB scripts
#
# DEBUG=yes export DEBUG
PATH=/bin:/sbin:/usr/sbin:/usr/bin
if [ -t -o ! -x /usr/bin/logger ]; then
mesg () {
echo "$@"
}
else
mesg () {
/usr/bin/logger -t $0 "$@"
}
fi
usage ()
{
# Only one parameter (event type) is mandatory.
# Everything else is type-specific.
if [ -t ]; then
echo "Usage: $0 {usb,pci,net,...} ..."
echo "Environment parameters are also type-specific."
# FIXME: list non-builtin agents (/etc/hotplug/*.agent)
else
mesg "illegal usage $*"
fi
exit 1
}
if [ "$DEBUG" != "" ]; then
mesg "arguments ($*) env (`env`)"
fi
# Only one required argument: event type type being dispatched.
# Examples: usb, pci, isapnp, net, ieee1394, printer, disk, ...
if [ $# -lt 1 ]; then
usage
elif [ $1 = help -o $1 = '--help' ]; then
usage
# Prefer to delegate event handling:
# /sbin/hotplug FOO ..args.. ==> /etc/hotplug/FOO.agent ..args..
#
elif [ -x /etc/hotplug/$1.agent ]; then
shift
exec /etc/hotplug/$1.agent "$@"
fi
####################################################################
#
# Builtin agent code -- "80% solution" fallbacks.
#
# For USB and PCI, this directly processes modutils (2.3.20+)
# output for MODULE_DEVICE_TABLE entries, so that you can hotplug
# after installing only this script.
#
# For network interfaces, if you've got "ifup" it'll try to
# bring the interface up. Otherwise, update for your distro.
#
#
# This module loading uses BASH ("declare -i") and some version of
# AWK, typically /bin/gawk. Most GNU/Linux distros have these,
# but some specialized ones (floppy based, etc) may not.
#
# NOTE: The match algorithms here aren't any smarter than those
# in the kernel; they take the first match available, even if
# it's not the "best" (most specific) match. That's not really
# a feature. Agents written in other language can more easily
# support sophisticated driver selection algorithms, prioritize
# (or add) administrator-specified bindings, and so on.
#
# FIXME: can we avoid using '<<' to parse composite variables?
# That may require a writable /tmp; do we fail cleanly in
# that phase of system bootstrapping?
AWK=gawk
MODDIR=/lib/modules/`uname -r`
# ISAPNP_MAP=$MODDIR/modules.isapnpmap
PCI_MAP=$MODDIR/modules.pcimap
USB_MAP=$MODDIR/modules.usbmap
####################################################################
#
# Kernel USB params are:
#
# ACTION=%s [add or remove]
# PRODUCT=%x/%x/%x
# INTERFACE=%d/%d/%d
# TYPE=%d/%d/%d
#
# And if usbdevfs is configured, also:
#
# DEVFS=/proc/bus/usb
# DEVICE=/proc/bus/usb/%03d/%03d
#
# If usbdevfs is mounted on /proc/bus/usb, $DEVICE is a file which
# can be read to get the device's current configuration descriptor.
#
declare -i usb_idVendor usb_idProduct usb_bcdDevice
declare -i usb_bDeviceClass usb_bDeviceSubClass usb_bDeviceProtocol
declare -i usb_bInterfaceClass usb_bInterfaceSubClass usb_bInterfaceProtocol
usb_convert_vars ()
{
local XPROD
XPROD=`echo $PRODUCT | $AWK -F/ '{print "0x" $1, "0x" $2, "0x" $3 }'`
read usb_idVendor usb_idProduct usb_bcdDevice << EOT
$XPROD
EOT
if [ x$TYPE != x ]; then
IFS=/ read usb_bDeviceClass usb_bDeviceSubClass usb_bDeviceProtocol << EOT
$TYPE
EOT
else
# out-of-range values
usb_bDeviceClass=1000
usb_bDeviceSubClass=1000
usb_bDeviceProtocol=1000
fi
if [ x$INTERFACE != x ]; then
IFS=/ read usb_bInterfaceClass usb_bInterfaceSubClass usb_bInterfaceProtocol << EOT
$INTERFACE
EOT
else
# out-of-range values
usb_bInterfaceClass=1000
usb_bInterfaceSubClass=1000
usb_bInterfaceProtocol=1000
fi
}
declare -i USB_ANY
USB_ANY=0
# stdin is "modules.usbmap" syntax
usb_map_modules ()
{
# convert the usb_device_id fields to integers as we read them
local module ignored
declare -i idVendor idProduct bcdDevice_lo bcdDevice_hi
declare -i bDeviceClass bDeviceSubClass bDeviceProtocol
declare -i bInterfaceClass bInterfaceSubClass bInterfaceProtocol
# comment line lists (current) usb_device_id field names
read ignored
# look at each usb_device_id entry
while read module idVendor idProduct bcdDevice_lo bcdDevice_hi bDeviceClass bDeviceSubClass bDeviceProtocol bInterfaceClass bInterfaceSubClass bInterfaceProtocol ignored
do
: checkmatch $module
: idVendor $idVendor $usb_idVendor
if [ $idVendor -ne $USB_ANY -a $idVendor -ne $usb_idVendor ]; then
continue
fi
# NOTE: zero product code isn't the wildcard!
: idProduct $idProduct $usb_idProduct
if [ $idVendor -ne $USB_ANY -a $idProduct -ne $usb_idProduct ]; then
continue
fi
: bcdDevice range $bcdDevice_hi $bcdDevice_lo actual $usb_bcdDevice
if [ $bcdDevice_lo -ge $usb_bcdDevice ]; then
continue
fi
if [ $bcdDevice_hi -ne $USB_ANY -a $bcdDevice_hi -ge $usb_bcdDevice ]; then
continue
fi
: bDeviceClass $bDeviceClass $usb_bDeviceClass
if [ $bDeviceClass -ne $USB_ANY -a $bDeviceClass -ne $usb_bDeviceClass ]; then
continue
fi
: bDeviceSubClass $bDeviceSubClass $usb_bDeviceSubClass
if [ $bDeviceSubClass -ne $USB_ANY -a $bDeviceSubClass -ne $usb_bDeviceSubClass ]; then
continue
fi
: bDeviceProtocol $bDeviceProtocol $usb_bDeviceProtocol
if [ $bDeviceProtocol -ne $USB_ANY -a $bDeviceProtocol -ne $usb_bDeviceProtocol ]; then
continue
fi
# NOTE: for now, this only checks the first of perhaps
# several interfaces for this device.
: bInterfaceClass $bInterfaceClass $usb_bInterfaceClass
if [ $bInterfaceClass -ne $USB_ANY -a $bInterfaceClass -ne $usb_bInterfaceClass ]; then
continue
fi
: bInterfaceSubClass $bInterfaceSubClass $usb_bInterfaceSubClass
if [ $bInterfaceSubClass -ne $USB_ANY -a $bInterfaceSubClass -ne $usb_bInterfaceSubClass ]; then
continue
fi
: bInterfaceProtocol $bInterfaceProtocol $usb_bInterfaceProtocol
if [ $bInterfaceProtocol -ne $USB_ANY -a $bInterfaceProtocol -ne $usb_bInterfaceProtocol ]; then
continue
fi
# It was a match!
DRIVER=$module
: driver $DRIVER
break;
done
}
####################################################################
#
# Kernel Cardbus/PCI params are (current patch):
#
# PCI_CLASS=%X
# PCI_ID=%X/%X
# PCI_SLOT_NAME=%s
# PCI_SUBSYS_ID=%X/%X
#
# If /proc is mounted, /proc/bus/pci/$PCI_SLOT_NAME is almost the name
# of the binary device descriptor file ... just change ':' to '/'.
#
declare -i pci_class
declare -i pci_id_vendor pci_id_device
declare -i pci_subid_vendor pci_subid_device
pci_convert_vars ()
{
XID=`echo $PCI_ID | $AWK -F/ '{print "0x" $1, "0x" $2 }'`
read pci_class pci_id_vendor pci_id_device << EOT
0x$PCI_CLASS $XID
EOT
XID=`echo $PCI_SUBSYS_ID | $AWK -F/ '{print "0x" $1, "0x" $2 }'`
read pci_subid_vendor pci_subid_device << EOT
$XID
EOT
}
declare -i PCI_ANY
PCI_ANY=0xffffffff
# stdin is "modules.pcimap" syntax
pci_map_modules ()
{
# convert the usb_device_id fields to integers as we read them
local module ignored
declare -i vendor device
declare -i subvendor subdevice
declare -i class class_mask
declare -i class_temp
# comment line lists (current) pci_device_id field names
read ignored
# look at each pci_device_id entry
while read module vendor device subvendor subdevice class class_mask ignored
do
: checkmatch $module
: vendor $vendor $pci_id_vendor
if [ $vendor -ne $PCI_ANY -a $vendor -ne $pci_id_vendor ]; then
continue
fi
: device $device $pci_id_device
if [ $device -ne $PCI_ANY -a $device -ne $pci_id_device ]; then
continue
fi
: sub-vendor $subvendor $pci_subid_vendor
if [ $subvendor -ne $PCI_ANY -a $subvendor -ne $pci_subid_vendor ]; then
continue
fi
: sub-device $subdevice $pci_subid_device
if [ $subdevice -ne $PCI_ANY -a $subdevice -ne $pci_subid_device ]; then
continue
fi
class_temp="$pci_class & $class_mask"
if [ $class_temp -eq $class ]; then
DRIVER=$module
: driver $DRIVER
break;
fi
done
}
####################################################################
#
# usage: load_driver type filename description
#
# (always) modprobes a single driver module, and optionally
# invokes a module-specific setup script.
#
load_driver ()
{
# find the driver using modutils output
if [ -f $2 ]; then
$1_convert_vars
$1_map_modules < $2
else
mesg "$2 missing"
exit 1
fi
if [ x$DRIVER = x ]; then
mesg "... no driver for $3"
exit 2
fi
if [ "$DEBUG" != "" ]; then
mesg Module $DRIVER matches $3
fi
# maybe the driver needs loading
if ! lsmod | grep "^$DRIVER "
then
if ! modprobe $DRIVER
then
mesg "... can't load module $DRIVER"
exit 3
fi
fi
# NOTE: this assumes that driver bound to
# this device; it'd be better to check ...
# run any setup script; no /etc/modules.conf changes needed
if [ -x /etc/hotplug/$1/$DRIVER ]; then
if [ "$DEBUG" != "" ]; then
mesg Driver setup: $DRIVER
fi
exec /etc/hotplug/$1/$DRIVER
else
exit 0
fi
}
####################################################################
#
# Two basic policy agents are now built in: they try to load the
# USB or PCI driver module corresponding to newly added devices.
# They're used as backup, in case no smarter tools are available.
#
if [ $1 = usb ]; then
# Until all kernel USB drivers get updated, you need:
# http://www.linux-usb.org/policy.html
if [ -f /etc/usb/policy ]; then
exec /etc/usb/policy
fi
if [ x$PRODUCT = x ]; then
mesg Bad USB invocation
exit 1
fi
# no more commandline params
case x$ACTION in
xadd)
load_driver usb $USB_MAP "USB product $PRODUCT"
# won't return
;;
xremove)
: USB remove, ignored
exit 0;;
x*|xhelp)
usage $* ;;
esac
elif [ $1 = pci ]; then
# NOTE: PCI includes CardBus
if [ x$PCI_CLASS = x ]; then
mesg Bad PCI invocation
exit 1
fi
case x$ACTION in
xadd)
if [ "$DEBUG" != "" -a -x /sbin/lspci ]; then
mesg New PCI Device: `/sbin/lspci -s $PCI_SLOT_NAME`
fi
load_driver pci $PCI_MAP "PCI device at slot $PCI_SLOT_NAME"
# won't return
;;
xremove)
: PCI remove, ignored
exit 0;;
*|help)
usage $* ;;
esac
elif [ $1 = net ]; then
if [ x$INTERFACE = x ]; then
mesg Bad NET invocation
exit 1
fi
if [ x$ACTION = xregister -a -x /sbin/ifup ]; then
/sbin/ifup $INTERFACE &
exit 0
fi
fi
mesg "$0: event type '$1' unsupported"
exit 1
^ permalink raw reply [flat|nested] only message in thread
only message in thread, other threads:[~2000-11-28 8:39 UTC | newest]
Thread overview: (only message) (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2000-11-28 0:09 sample /sbin/hotplug script David Brownell
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox