#!/bin/sh
# $Id: usb,v 1.16 2002/06/04 16:38:01 ldv Exp $	
#
# usb	        This shell script takes care of starting and stopping
#               your usb devices.
#
# chkconfig: 2345 04 91
# description: This startup script try to load your modules for your usb devices.

if [ -f /etc/modules.conf ]; then
	conf_file=/etc/modules.conf
elif [ -f /etc/conf.modules ]; then
	conf_file=/etc/conf.modules
else
	exit 1
fi

if fgrep -iwqs nousb /proc/cmdline; then
	exit 0
fi

LOCKFILE=/var/lock/subsys/usb

. /etc/init.d/functions

SourceIfNotEmpty /etc/sysconfig/usb && [ "$USB" == yes ] || exit 0

PKLVL=
exit_handler()
{
	RETVAL=$?
	trap '' EXIT
	[ -z "$PKLVL" ] || sysctl -w "kernel.printk=$PKLVL"
	PKLVL=
	exit $RETVAL
}

set_pklvl()
{
	PKLVL=`cut -f1 /proc/sys/kernel/printk` &&
		trap 'exit_handler' SIGHUP SIGINT SIGQUIT SIGTERM EXIT &&
		sysctl -w kernel.printk=0
}

ARCH="$(uname -m)"

function set_usb_interface()
{
	local module=$1
	echo "alias usb-interface $module" >>$conf_file
	# shut your mounth, modprobe :\
	depmod -A
}

function probe_usb_interface () {
    local t pci_f uhci_t ohci_t

    pci_f=/proc/bus/pci/devices
    uhci_t="11063038 80862422 80867020 80867112 80867602 80862412"
    ohci_t="0e117020 0e11a0f8 10227404 1022740c 10330035 10397001 1045a0f8 1045c861 10950670 10950673 10b95237 106b0019 11c15801"

    # let's try with lspcidrake, he has everything we need and should
    # do thing better
    if [ -x /usr/bin/lspcidrake ];then
	t=$(lspcidrake|sed -n 's/.*USB.* \(.*\))$/\1/p')
	if [ -n "$t" ];then
	    set_usb_interface $t
	    return 0;
	fi
    fi
    # Ok nothing let's try to detect it by ourself and pci id
    # aka: i have some time to lost in the airplane
    for i in $uhci_t;do
	if grep -q ".*$i.*" $pci_f;then
	    set_usb_interface usb-uhci
	    return 0
	fi
    done
    for i in $ohci_t;do
	if grep -q ".*$i.*" $pci_f;then
	    set_usb_interface usb-ohci
	    return 0
	fi
    done
    return 1;
}

function get_usb_interface () {
	if ! grep -qs "^alias usb-interface" $conf_file; then
		if ! probe_usb_interface; then
			action "USB Interface not found:" /bin/true
			exit 1
		else
			action "Detecting USB interface:" /bin/true
		fi
	fi
}

function mount_proc_usb () {
	if fgrep -qs usbdevfs /proc/filesystems && ! fgrep -qs /proc/bus/usb /proc/mounts; then
		action "Mounting USB filesystem:" mount -t usbdevfs usbdevfs /proc/bus/usb
	fi
}

function umount_proc_usb () {
	if [ -d /proc/bus/usb ] && fgrep -qs usbdevfs /proc/filesystems && fgrep -qs /proc/bus/usb /proc/mounts; then
		action "Unmounting USB filesystem:" umount /proc/bus/usb
	fi
}

function detect_devices () {
	OIFS="$IFS"
	IFS=
	if [ -r /proc/bus/usb/devices ];then
		dev=$(cat /proc/bus/usb/devices)
	else
		return;
	fi
	if echo $dev|grep -qE "^I.*Cls=03.*Prot=02" && [ -z "$MOUSE" ]; then
		export MOUSE=yes
	fi
	if echo $dev|grep -qE "^I.*Cls=03.*Prot=01" && [ -z "$KEYBOARD" ]; then
		export KEYBOARD=yes
	fi
	if echo $dev|grep -qE "^I.*Cls=08\(stor.\)" && [ -z "$STORAGE" ]; then
		export STORAGE=yes
	fi
	if echo $dev|grep -qE "^I.*Cls=07\(print\)" && [ -z "$PRINTER" ]; then
		export PRINTER=yes
	fi
	IFS="$OIFS"
}
    

if grep -qs '^alias usbmouse' $conf_file; then
	# Backward compatibility: No good sed it
	sed 's|^alias usbmouse|alias usb-interface|' <$conf_file >/tmp/.conf.modules.tmp &&
		mv -f /tmp/.conf.modules.tmp $conf_file &&
		depmod -A
fi

PKLVL=`cut -f1 /proc/sys/kernel/printk`

load_interfaces ()
{
	local key name value
	# Loop over every usb-interface line in /etc/modules.conf.
	cat $conf_file |while read key name value; do
		[ "$key" = alias ] || continue
		[ -z "${name##usb-interface*}" ] || continue

		if /sbin/modprobe "$name"; then
			action "Loading USB interface ($value):" /bin/true
		else
			action "Disabling USB interface ($value):" /bin/true
		fi
	done
}

unload_interfaces ()
{
	local key name value
	# Loop over every usb-interface line in /etc/modules.conf.
	cat $conf_file |while read key name value; do
		[ "$key" = alias ] || continue
		[ -z "${name##usb-interface*}" ] || continue

		action "Unloading USB interface ($value):" /sbin/modprobe -r "$name"
	done
}

start()
{
	get_usb_interface
	set_pklvl
	load_interfaces
	fgrep -qs usb /proc/devices || exit
	
	mount_proc_usb
	sleep 2
	detect_devices
	if [ "$MOUSE" = "yes" ];then
		action "Loading USB mouse:" /sbin/modprobe usbmouse && /sbin/modprobe mousedev
	fi
	if [ "$KEYBOARD" = "yes" ];then
		action "Loading USB keyboard:" /sbin/modprobe usbkbd && /sbin/modprobe keybdev
	fi
	if [ "$STORAGE" = "yes" ];then
		action "Loading USB storage:"  /sbin/modprobe usb-storage
	fi
	if [ "$PRINTER" = "yes" ];then
		action "Loading USB printer:"  /sbin/modprobe printer
	fi
	if [ "$VISOR" = "yes" ];then
		action "Loading USB visor:"  /sbin/modprobe visor
	fi

	touch "$LOCKFILE"
	sleep 1
}

stop()
{
	set_pklvl
	detect_devices

	if [ "$MOUSE" = "yes" ];then
		action "Unloading USB mouse:" /sbin/modprobe -r mousedev && /sbin/modprobe -r usbmouse
	fi
	if [ "$KEYBOARD" = "yes" ];then
		action "Unloading USB keyboard:" /sbin/modprobe -r keybdev && /sbin/modprobe -r usbkbd
	fi
	if [ "$STORAGE" = "yes" ];then
		action "Unloading USB storage:" /sbin/modprobe -r usb-storage
	fi
	if [ "$PRINTER" = "yes" ];then
		action "Unloading USB printer:" /sbin/modprobe -r printer
	fi
	if [ "$VISOR" = "yes" ];then
		action "Unloading USB visor:" /sbin/modprobe -r visor
	fi
	umount_proc_usb
	unload_interfaces

	rm -f "$LOCKFILE"
	sleep 1
}

case $1 in 
	start)
		start
		;;
	stop)
		stop
		;;
	status)
		if [ -e /proc/bus/usb/devices ]; then
			echo "USB Loaded."
		else
			echo "USB not loaded."
		fi
		;;
	restart|reload)
		stop
		start
		;;
	*)
		echo "Usage: ${0##*/} {start|stop|restart|status}"
		;;
esac

exit 0
