[/url])
automatically when you connect your USB HandSpring Visor to the
computer, the following script located at /sbin/hotplug would work well:
#!/bin/shUSER=gregkhif
[ "$1" = "usb" ]; then if [ "$PRODUCT" = "82d/100/0" ]; then
if [ "$ACTION" = "add" ]; then modprobe visor
su $USER - -c "/usr/bin/coldsync" else rmmod visor
fi fifiIf you want to make sure that your network
devices always come up connected to the proper Ethernet card, the
following /sbin/hotplug script, contributed by Sukadev Bhattiprolu, can
do this: #!/bin/shif [ "$1" = "network" ]; then if [ "$ACTION" = "register" ]; then nameif -r $INTERFACE -c /etc/mactab fifiListing
1 shows a more complex example that can handle automatically loading
and unloading modules for three different USB devices.
Need for Automation
The
previous small example shows the limitations of being forced to enter
in all of the different device IDs manually, product IDs and such in
order to keep a /sbin/hotplug script up to date with all of the
different devices that the kernel knows about. Instead, it would be
better for the kernel itself to specify the different types of devices
that it supports in such a way that any user-space tools could read
them. Thus was born a macro called MODULE_DEVICE_TABLE() that is used by
all USB and PCI drivers. This macro describes which devices each
specific driver can support. At compilation time, the build process
extracts this information out of the driver and builds a table. The
table is called modules.pcimap and modules.usbmap for all PCI and USB
devices, respectively, and exists in the directory /lib/modules/kernel_version/.
For example, the following code snippet from drivers/net/eepro100.c:
static
struct pci_device_id eepro100_pci_tbl[]__devinitdata = { {
PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82557, PCI_ANY_ID,
PCI_ANY_ID, }, { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82562ET,
PCI_ANY_ID, PCI_ANY_ID, }, { PCI_VENDOR_ID_INTEL,
PCI_DEVICE_ID_INTEL _82559ER, PCI_ANY_ID, PCI_ANY_ID,},
{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL _ID1029,
PCI_ANY_ID, PCI_ANY_ID,}, { PCI_VENDOR_ID_INTEL,
PCI_DEVICE_ID_INTEL _ID1030, PCI_ANY_ID, PCI_ANY_ID,}, {
PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL _82801BA_7,
PCI_ANY_ID, PCI_ANY_ID,}, { 0,} }; MODULE_DEVICE_TABLE(pci,
eepro100_pci_tbl);causes these lines to be added to the modules.pcimap file:
eepro100
0x00008086 0x00001229 0xffffffff 0xffffffff0x00000000 0x00000000
0x00000000eepro100 0x00008086 0x00001031 0xffffffff 0xffffffff0x00000000
0x00000000 0x00000000eepro100 0x00008086 0x00001209 0xffffffff
0xffffffff0x00000000 0x00000000 0x00000000eepro100 0x00008086 0x00001029
0xffffffff 0xffffffff0x00000000 0x00000000 0x00000000eepro100
0x00008086 0x00001030 0xffffffff 0xffffffff0x00000000 0x00000000
0x00000000eepro100 0x00008086 0x00002449 0xffffffff 0xffffffff0x00000000
0x00000000 0x00000000As the example shows, a PCI device can be specified by any of the same parameters that are passed to the /sbin/hotplug program.
A USB device can specify that it can accept only specific devices such as this example from drivers/usb/mdc800.c:
static
struct usb_device_id mdc800_table [] = { {
USB_DEVICE(MDC800_VENDOR_ID, MDC800_PRODUCT_ID) }, { } /* Terminating
entry */};MODULE_DEVICE_TABLE(usb, mdc800_table);which causes the following line to be added to the modules.usbmap file:
mdc800 0x0003 0x055f 0xa800 0x0000 0x0000 0x00 0x000x00 0x00 0x00 0x00 0x00000000Or
it can specify that it accepts any device that matches a specific USB
class code, as in this example from drivers/usb/printer.c: static
struct usb_device_id usblp_ids [] = { {
USB_INTERFACE_INFO(USB_CLASS_PRINTER, 1, 1) }, {
USB_INTERFACE_INFO(USB_CLASS_PRINTER, 1, 2) }, {
USB_INTERFACE_INFO(USB_CLASS_PRINTER, 1, 3) }, { } /* Terminating
entry */};MODULE_DEVICE_TABLE(usb, usblp_ids);which causes the following lines to be added to the modules.usbmap file: printer
0x0380 0x0000 0x0000 0x0000 0x0000 0x00 0x000x00 0x07 0x01 0x01
0x00000000printer 0x0380 0x0000 0x0000 0x0000 0x0000 0x00 0x000x00 0x07
0x01 0x02 0x00000000printer 0x0380 0x0000 0x0000 0x0000 0x0000 0x00
0x000x00 0x07 0x01 0x03 0x00000000Again these USB examples show
that the information in the modules.usbmap file matches the information
provided to /sbin/hotplug by the kernel, enabling /sbin/hotplug to
determine which driver to load without relying on a hand-generated
table, as PCMCIA does.
Preprocessor Abuse
The
macro MODULE_DEVICE_TABLE automatically creates two variables. For the
example: MODULE_DEVICE_TABLE (usb, usblp_ids); the variables
__module_usb_device_size and __module_usb_device_table are created and
placed into the read-only data section and the initialized data section
of the module, respectively. The variable __module_usb_device_size
contains the value of the size of the struct usb_id structure, and
__module_usb_device_table points to the usblp_ids structure. The
usblp_ids variable is an array of usb_id structures with a terminating
NULL structure at the end of the list.
When
the depmod program is run, as part of the kernel installation process,
it goes through every module looking for the symbol
__module_usb_device_size to be present in the compiled module. If it
finds it, it copies the data pointed to by the __module_usb_device_table
symbol into a structure, extracts all of the information and writes it
out to the modules.usbmap file, which is located in the module root
directory. It does the same thing while looking for the
__module_pci_device_size in creating the modules.pcimap file.
With
the kernel module information exported to the files modules.usbmap and
modules.pcimap, our version of /sbin/hotplug can look like Listing 2
[available at].
This example only tests for a match of the USB product ID and vendor
IDs. The Linux-Hotplug Project has created a set of scripts that covers
all of the different subsystems that can call /sbin/hotplug. This
enables drivers to be loaded automatically when new devices are inserted
into the systems. It also starts up network services when network
devices are seen. These scripts are released under the GPL and are
available at . Almost all major Linux distributions are currently shipping this package, so it is probably already on your machine.
The Future
The
current /sbin/hotplug subsystem needs to be incorporated into other
kernel systems, as they develop hot-plug capability. SCSI, IDE and other
systems all have hot-plug patches available for kernel support but need
to have script support, kernel macro support and modutils depmod
support added in order to provide the user with a consistent experience.
As
the kernel boots, and discovers new devices, it tries to spawn
/sbin/hotplug, but since user space has not been initialized yet, it
cannot run. This means that any USB or PCI devices that are needed at
boot time need to be compiled into the kernel or exist in an initrd RAM
disk image as a module. Sometime during the 2.5 development process, the
initrd RAM disk image will be converted to contain an entire small
user-space tree. This will allow /sbin/hotplug to be run during the boot
process and load modules dynamically. Some links describing this disk
image idea are: ,, and .
Because
of the small space requirements of this RAM disk image, the dietHotplug
program has been written. It is an implementation of the Linux-Hotplug
bash scripts in C and does not require modules.*map files when the
program runs. The executable size of the entire dietHotplug program is
one-fifth of the size of the original modules.*map files themselves. The
small size is due to the use of dietLibc (found at) and other space-saving techniques. dietHotplug will undergo more development as the 2.5 kernel requirements are more fully known. dietHotplug can be downloaded from the Linux-Hotplug site.
Acknowledgements
I
would like to thank David Brownell who wrote the original /sbin/hotplug
kernel patch and most of the Linux Hotplug scripts. Without his
persistence, Linux would not have this user-friendly feature. I also
would like to acknowledge the entire Linux USB development team, who
have provided a solid kernel subsystem in a relatively short amount of
time.
Keith
Owens wrote the supporting code in the depmod utility and has endured
constant changes to the format of the MODULE_DEVICE_TABLE() USB
structure.
The
other developers on the linux-hotplug-devel mailing list who have helped
with their patches and feedback on the hot-plug scripts also deserve
recognition, along with the wonderful Linux distribution-specific
support that Debian, Red Hat and Mandrake have provided.
This article was based upon a paper and presentation that I gave at the 2001 Ottawa Linux Symposium.
Greg Kroah-Hartman is
currently the Linux USB and PCI Hotplug kernel maintainer. He works for
IBM, doing various LInux kernel-related things and can be reached at .
email:
转自: