#!/bin/sh
#
# zaptel        This shell script takes care of loading and unloading \
#               Zapata Telephony interfaces
# chkconfig: 2345 9 92
# description: The zapata telephony drivers allow you to use your linux \
# computer to accept incoming data and voice interfaces
#
# config: /etc/sysconfig/zaptel

### BEGIN INIT INFO
# Provides: zaptel
# Shold-Start: dkms
# Default-Start: 3 4 5
# Short-Description: Zaptel kernel module
# Description: The zapata telephony drivers allow you to use your linux
#              computer to accept incoming data and voice interfaces
### END INIT INFO

# Source function library.
. /etc/rc.d/init.d/functions || exit 0

# source the zaptel configuration
[ -f /etc/sysconfig/zaptel ] && . /etc/sysconfig/zaptel

# recursively unload a module and its dependencies, if possible.
# where's modprobe -r when you need it?
# inputs: module to unload.
# returns: the result from
unload_module() {
	module="$1"
	line=`lsmod 2>/dev/null | grep "^$1 "`
	if [ "$line" = '' ]; then 
		gprintf "No zaptel modules found\n"
		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) 
		# TODO: the following is probably the error handling we want:
		# if [ $? != 0 ]; then return 1; fi
	done	
	action "Unloading zaptel module %s:" "$module" rmmod $module
}

# 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

	gprintf "Waiting for Astribank devices to initialize:\n"
	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 auto
}

shutdown_dynamic() {
	if ! grep -q ' ZTD/' /proc/* 2>/dev/null; then return; fi

	# we should only get here if we have dynamic spans. Right?
	ztcfg -s
}

test_zap() {
 	TMOUT=20 # max secs to wait
 	while [ ! -d /dev/zap ] ; do
  		sleep 1
 		TMOUT=`expr $TMOUT - 1`
 		if [ $TMOUT -eq 0 ] ; then
 			# gprintf "Error: missing /dev/zap!\n"
 			RETVAL=1
 			exit 1
 		fi
 	done
 }

# Check that telephony is up.
if [ "${TELEPHONY}" != "yes" ]; then
       gprintf "No TELEPHONY found\n"
       exit 0
fi

if [ ! -x "/sbin/ztcfg" ]; then
       gprintf "ztcfg not executable\n"
       exit 0
fi

if [ ! -f /etc/zaptel.conf ]; then
       gprintf "/etc/zaptel.conf not found\n"
       exit 0
fi

if [ "${DEBUG}" = "yes" ]; then
	ARGS="debug=1"
fi

RETVAL=0

# See how we were called.
case "$1" in
  start)
	# Load drivers
	rmmod wcusb 2> /dev/null
	rmmod wcfxsusb 2> /dev/null
	rmmod audio 2> /dev/null
	action "Loading zaptel framework: " modprobe zaptel ${ARGS}
	action "Waiting for zap to come online: " test_zap
	echo ""
	for x in $MODULES; do 
		eval localARGS="\$${x}_ARGS"
		action "Loading zaptel module ${x}: " modprobe ${x} ${ARGS} ${localARGS} 2> /dev/null
	done
	sleep 3 # TODO: remove it
	
	# If you have zaptel-perl, the three below can be replaced with:
	xpp_startup
	
	if [ ! -e /proc/zaptel/1 ]; then
		echo ""
		gprintf "No functioning zap hardware found in /proc/zaptel so unload modules\n"
		for x in $MODULES; do
			action "Unloading zaptel module %s: " "${x}" modprobe -r ${x}
		done
		echo ""
		action "Loading zaptel module ztdummy: " modprobe ztdummy
		# wait a few seconds before running ztcfg below
		sleep 3
	fi
	action "Running ztcfg: " ztcfg -vv
	RETVAL=$?

	[ $RETVAL -eq 0 ] && touch /var/lock/subsys/zaptel
	if [ -x "/sbin/fxotune" ] && [ -r /etc/fxotune.conf ]; then
		# Allowed to fail if e.g. Asterisk already uses channels:
		/sbin/fxotune -s || : 
	fi
	;;
  stop)
	# Unload drivers
	
	#shutdown_dynamic # FIXME: needs test from someone with dynamic spans
	gprintf "Unloading zaptel hardware drivers:\n"
  	unload_module zaptel
	RETVAL=$?
	gprintf ".\n"
	[ $RETVAL -eq 0 ] && rm -f /var/lock/subsys/zaptel
	;;
  unload)
	# We don't have zaptel helper, so let's not replicate too much code:
	# allow others to use the unload command.
	unload_module zaptel
	;;
  restart)
	$0 stop
	$0 start
	;;
  reload)
	action "Reloading ztcfg: " /sbin/ztcfg
	RETVAL=$?
	;;
  status)
	status zaptel
	;;
  *)
	gprintf "Usage: zaptel {start|stop|restart|reload|status}\n"
	exit 1
esac

exit $RETVAL
