#! /bin/sh

### BEGIN INIT INFO
# Provides:          zaptel
# Required-Start:    
# Required-Stop:     
# Should-Start:      $local_fs hotplug module-init-tools
# Should-Stop:       $local_fs
# Default-Start:     2 3 4 5
# Default-Stop:      0 1 6
# Short-Description: Configures zaptel kernel modules.
# Description:       Configures zaptel kernel modules. Waits until
#                    they are fully loaded or loads ztdummy (if modules
#                    are availble).
### END INIT INFO

PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
DAEMON=/sbin/ztcfg
ZAPCONF_FILE=/etc/zaptel.conf
NAME=zaptel
DESC="Zaptel telephony kernel driver"
FXOTUNE=/sbin/fxotune
XPP_SYNC=auto

# Include am defaults if available
if [ -f /etc/default/zaptel ] ; then
	. /etc/default/zaptel
fi

if [ ! -x $DAEMON ] ; then
	echo >&2 $NAME ":" $DAEMON "fails test for exists and executable" ;
	exit 0
fi

# defined in /etc/default/zaptel
# ZAPTEL_MODS is a list of modules to be loaded at startup

set -e

# Initialize the Xorcom Astribank (xpp/) using perl utiliites:
# intended to replace all the the three functions below if user has 
# installed the zaptel-perl utilities.
xpp_startup() {
	# do nothing if there are no astribank devices:
	if ! grep -q connected /proc/xpp/xbuses 2>/dev/null; then return 0; fi

	echo "Waiting for Astribank devices to initialize:"
	cat /proc/xpp/XBUS-[0-9]*/waitfor_xpds 2>/dev/null || true
	
	# overriding locales for the above two, as perl can be noisy
	# when locales are missing.
	# No register all the devices if they didn't auto-register:
	LC_ALL=C zt_registration on

	# this one could actually be run after ztcfg:
	LC_ALL=C xpp_sync "$XPP_SYNC"
}

# recursively unload a module and its dependencies, if possible.
# where's modprobe -r when you need it?
# inputs: module to unload.
unload_module() {
	set +e
	module="$1"
	line=`lsmod 2>/dev/null | grep "^$module "`
	if [ "$line" = '' ]; then return; fi # module was not loaded

	set -- $line
	# $1: the original module, $2: size, $3: refcount, $4: deps list
	mods=`echo $4 | tr , ' '`
	# xpp_usb keeps the xpds below busy if an xpp hardware is
	# connected. Hence must be removed before them:
	case "$module" in xpd_*) mods="xpp_usb $mods";; esac
	for mod in $mods; do
		# run in a subshell, so it won't step over our vars:
		(unload_module $mod) 
	done
	rmmod $module || true
	set -e
}

# this checks that:
# A. /dev/zap/pseudo exists (if devfs/udev is in use, it implies zaptel loaded)
# B. Readable to the user running this script. No poblem if run by root.
# C. There is an active zaptel timing source. Either a zaptel hardware
#    device or ztdummy.
test_zaptel_timing() {
	head -c 0 /dev/zap/pseudo 2>/dev/null
}

case "$1" in
	start|reload)
		echo -n "$DESC: "
		#for module in $ZAPTEL_MODS
		#do
		#	modprobe $module
		#done
                xpp_startup
		
		# If there is no zaptel timing source, load
		# ztdummy. Other modules should have been loaded by
		# now.
		if ! test_zaptel_timing
		then modprobe ztdummy || true # will fail if there is no module package
		fi

		# configure existing modules:

		#If we got here and we have no zaptel modules, there's
		# no point to fail if zaptel-modules-version> is not
		# installed.
		if [ ! -d /proc/zaptel ]; then
			exit 0 # no modules loaded
		fi

		$DAEMON $DAEMON_OPTS

                if [ -r /etc/fxotune.conf ] && [ -x $FXOTUNE ]; then
			# fxotune will fail if e.g. Asterisk is already running.
                	$FXOTUNE -s || :
                fi
		echo "$NAME."
		;;
	stop)
		: # do nothing
		;;
	unload)
		unload_module zaptel
		# if oslec is the echo canceller, loading zaptel will
		# also load oslec. Thus we need to be able to unload it
		# as well:
		unload_module oslec
		;;
	status)
		check_zaptel_timing
		;;
	force-reload|restart) 
		# there's no 'stop'
		$0 start
		;;
  *)
		N=/etc/init.d/$NAME
		echo "Usage: $N {start|stop|restart|force-reload|status|unload}" >&2
	exit 1
	;;
esac

exit 0
