#!/bin/sh

# Author   : Jean-Sebastien VALETTE <jean-sebastien.valette@libertysurf.fr>
# Creation : 06/12/2001
# Licence  : GPL

# 29/07/2003 crevetor :
# Added code to support the 2.6 kernel series.

# 23/10/2002 wwp:
# removed ugly hardcoded pathes, used new scheme.

# 21/10/2002 wwp:
# default .bin is synch01.bin now, /etc/eciadsl/synch.bin is a symlink to this one!
# removed ugly modutils uses, added some delays.

# 03/02/2002: added a sleep 2 after loading USB controller driver, as suggested
# by Sebastien YAPO <sebastien.yapo@free.fr>.

# 07/02/2002: added the CVS Id
# CVS $Id: startmodem,v 1.55 2003/08/01 14:14:02 crevetor Exp $
# Tag $Name:  $

# 15/02/2002 Benoit PAPILLAULT
#   remove "modprobe uhci" since this module never worked with this modem

# 13/06/2002 Sebastien HELLEU <flashcode@free.fr>
#   new file: /etc/eciadsl/vidpid : contains vid/pid (1 & 2) for your modem
#             example of content ECI:   0547 2131 0915 8000

# 03/07/2002 Sebastien HELLEU <flashcode@free.fr>
#   new file: /etc/eciadsl/eci_wan.bin (created by Makefile and eciconf) :
#             this is a link to your .bin
#   to change your .bin file, run eciconf or type this command :
#     rm /etc/eciadsl/eci_wan.bin && ln -s /path/your.bin /etc/eciadsl/eci_wan.bin


function wait_for_iface()
{
	echo -e "\nsetting up route table (5/5)..\n"
	# Wait until ppp0 get available
	COUNTER=10
	FLREADY=0
	TIMES=1
	echo -n "waiting for $1.."
	while [ $TIMES -le $COUNTER ]; do
    	ifconfig $1> /dev/null 2>&1
    	if [ $? -eq 0 ]; then
        	FLREADY=1
        	break
    	fi
    	sleep 1
    	echo -n "."
		TIMES=$(expr $TIMES + 1)
	done
	echo
	if [ "$FLREADY" -eq 0 ]; then
		echo "no $1 device found"
		exit -1
	fi
}


# <CONFIG>
BIN_DIR="/usr/local/bin"
ETC_DIR="/etc"
CONF_DIR="/etc/eciadsl"
PPPD_DIR="/etc/ppp"
VERSION=""
# </CONFIG>


if [ "$1" == "--version" -o "$1" == "-v" ]; then
	echo "$VERSION"
	exit 0
fi

if [ -s "$CONF_DIR/eciadsl.conf" ]; then
	vid1=`grep -E "^[ \t]*VID1[ \t]*=" "$CONF_DIR/eciadsl.conf" | tail -1 | cut -f 2 -d '=' | tr -d " \t"`
	pid1=`grep -E "^[ \t]*PID1[ \t]*=" "$CONF_DIR/eciadsl.conf" | tail -1 | cut -f 2 -d '=' | tr -d " \t"`
	vid2=`grep -E "^[ \t]*VID2[ \t]*=" "$CONF_DIR/eciadsl.conf" | tail -1 | cut -f 2 -d '=' | tr -d " \t"`
	pid2=`grep -E "^[ \t]*PID2[ \t]*=" "$CONF_DIR/eciadsl.conf" | tail -1 | cut -f 2 -d '=' | tr -d " \t"`
	mode=`grep -E "^[ \t]*MODE[ \t]*=" "$CONF_DIR/eciadsl.conf" | tail -1 | cut -f 2 -d '=' | tr -d " \t"`
	firmware=`grep -E "^[ \t]*FIRMWARE[ \t]*=" "$CONF_DIR/eciadsl.conf" | tail -1 | cut -f 2 -d '=' | tr -s "\t" " "`
	synch=`grep -E "^[ \t]*SYNCH[ \t]*=" "$CONF_DIR/eciadsl.conf" | tail -1 | cut -f 2 -d '=' | tr -s "\t" " "`
	staticip=`grep -E "^[ \t]*STATICIP[ \t]*=" "$CONF_DIR/eciadsl.conf" | tail -1 | cut -f 2 -d '=' | tr -d " \t"`
	gateway=`grep -E "^[ \t]*GATEWAY[ \t]*=" "$CONF_DIR/eciadsl.conf" | tail -1 | cut -f 2 -d '=' | tr -d " \t"`
	use_staticip=`grep -E "^[ \t]*USE_STATICIP[ \t]*=" "$CONF_DIR/eciadsl.conf" | tail -1 | cut -f 2 -d '=' | tr -d " \t"`
	use_dhcp=`grep -E "^[ \t]*USE_DHCP[ \t]*=" "$CONF_DIR/eciadsl.conf" | tail -1 | cut -f 2 -d '=' | tr -d " \t"`
	eciload1_options=`grep -E "^[ \t]*ECILOAD1_OPTIONS[ \t]*=" "$CONF_DIR/eciadsl.conf" | tail -1 | cut -f 2 -d '=' | tr -s "\t" " "`
	eciload2_options=`grep -E "^[ \t]*ECILOAD2_OPTIONS[ \t]*=" "$CONF_DIR/eciadsl.conf" | tail -1 | cut -f 2 -d '=' | tr -s "\t" " "`
	pppoeci_options=`grep -E "^[ \t]*PPPOECI_OPTIONS[ \t]*=" "$CONF_DIR/eciadsl.conf" | tail -1 | cut -f 2 -d '=' | tr -s "\t" " "`
	synch_attempts=`grep -E "^[ \t]*SYNCH_ATTEMPTS[ \t]*=" "$CONF_DIR/eciadsl.conf" | tail -1 | cut -f 2 -d '=' | tr -d " \t"`
	preferred_usb_hub=`grep -E "^[ \t]*PREFERRED_USB_HUB[ \t]*=" "$CONF_DIR/eciadsl.conf" | tail -1 | cut -f 2 -d '=' | tr -s "\t" " "`
else
	echo -e "\ncouldn't find $CONF_DIR/eciadsl.conf, default config assumed"
fi
test -z "$vid1" && vid1="0547"
test -z "$pid1" && pid1="2131"
test -z "$vid2" && vid2="0915"
test -z "$pid2" && pid2="8000"
test -z "$mode" && mode="$($BIN_DIR/pppoeci --modes 2>&1 | grep default |cut -d ' ' -f 1)"
test -z "$firmware" && firmware="$CONF_DIR/firmware00.bin"
test -z "$synch" && synch="$CONF_DIR/synch01.bin"
test -z "$synch_attempts" && synch_attempts=1

ps ax | grep pppoeci | grep -v grep > /dev/null 1>&1
if [ $? -eq 0 ]
then
	echo "aborting: pppoeci seems to be already running"
	echo "you should kill all instances of pppoeci and restart this script"
	exit -1
fi

echo -e "\nsetting up USB support (1/5).."

if [ ! -d /proc/bus/usb ]; then
    modprobe usbcore > /dev/null
	sleep 1
fi

# mount usbdevfs is this is not the case
mount | grep usbdevfs > /dev/null
if [ $? -ne 0 ]; then
    echo -e "\nloading preliminary USB device filesystem" 
    mount -t usbdevfs none /proc/bus/usb
	sleep 1
	mount | grep usbdevfs > /dev/null
	if [ $? -eq 0 ]; then
		echo "couldn't mount usbdevfs"
	else
		echo "usbdevfs mounted successfully"
	fi
fi

#verify if dabusb is loaded
lsmod | grep dabusb > /dev/null
if [ $? -eq 0 ]; then
    echo -e "\ndabusb seems to be present trying to remove it..."
    modprobe -r dabusb
	sleep 1
    lsmod | grep dabusb > /dev/null
	if [ $? -eq 0 ]; then
		echo "couldn't remove dabusb try to rmmod dabusb manually"
	else
		echo "dabusb removed successfully"
	fi
fi

#verify if ehci-hcd is loaded
lsmod | grep ehci-hcd > /dev/null
if [ $? -eq 0 ]; then
    echo -e "\nehci-hcd seems to be present trying to remove it..."
    modprobe -r ehci-hcd
	sleep 1
    lsmod | grep ehci-hcd > /dev/null
	if [ $? -eq 0 ]; then
		echo "couldn't remove ehci-hcd try to rmmod ehci-hcd manually"
	else
		echo "ehci-hcd removed successfully"
	fi
fi

minor_v=`uname -r | cut -d . -f 2` #minor kernel version : this is to check if we're running a 2.6 and to load the right usb module if this is the case.
if [ -z "$preferred_usb_hub" ]
then
	# try to locate UHCI controller
	lspci -v | grep -A 4 USB  | grep I/O > /dev/null
	if [ $? -eq 0 ]; then
		# ok, we have a UHCI controller, check if the linux driver is loaded
    	#grep "^S:  Product=USB UHCI Root Hub" /proc/bus/usb/devices > /dev/null
	lsmod | grep uhci > /dev/null
    	if [ $? -ne 0 ]; then
        	echo -e "\nloading UHCI support"
			if [ $minor_v -eq 4 ]
			then
				modprobe -l | grep usb-uhci > /dev/null
				if [ $? -ne 0 ]; then
					echo "warning: usb-uhci module doesn't exist"
				else
				modprobe usb-uhci
				sleep 2
				lsmod | grep usb-uhci > /dev/null
					if [ $? -ne 0 ]; then
						echo "couldn't load usb-uhci module"
					else
						echo "usb-uhci loaded successfully"
					fi
				fi
			elif [ $minor_v -ge 5 ]
			then
				modprobe -l | grep uhci-hcd > /dev/null
				if [ $? -ne 0 ]; then
					echo "warning: uhci-hcd module doesn't exist"
				else
				sleep 1
				modprobe uhci-hcd
				sleep 2
				lsmod | grep uhci-hcd > /dev/null
					if [ $? -ne 0 ]; then
						echo "couldn't load uhci-hcd module"
					else
						echo "uhci-hcd loaded successfully"
					fi
				fi
			fi
    	fi
	fi

	# try to locate OHCI controller
	lspci -v | grep -A 4 USB | grep memory > /dev/null
	if [ $? -eq 0 ]; then
		# ok, we have a OHCI controller, check if the linux driver is loaded
    	#grep "^S:  Product=USB OHCI Root Hub" /proc/bus/usb/devices > /dev/null
	lsmod | grep ohci > /dev/null
    	if [ $? -ne 0 ]; then
        	echo -e "\nloading OHCI support"
			if [ $minor_v -eq 4 ]
			then
				modprobe -l | grep usb-ohci > /dev/null
				if [ $? -ne 0 ]; then
					echo "warning: usb-ohci module doesn't exist"
				else
				modprobe usb-ohci
				sleep 2
				lsmod | grep usb-ohci > /dev/null
					if [ $? -ne 0 ]; then
						echo "couldn't load usb-ohci module"
					else
						echo "usb-ohci loaded successfully"
					fi
				fi
			elif [ $minor_v -ge 5 ]
			then
				modprobe -l | grep ohci-hcd > /dev/null
				if [ $? -ne 0 ]; then
					echo "warning: ohci-hcd module doesn't exist"
				else
				modprobe ohci-hcd
				sleep 2
				lsmod | grep ohci-hcd > /dev/null
					if [ $? -ne 0 ]; then
						echo "couldn't load ohci-hcd module"
					else
						echo "ohci-hcd loaded successfully"
					fi
				fi
			fi
    	fi
	fi
else
    echo -e "\nloading USB HUB support ($preferred_usb_hub)"
	modprobe -l | grep $preferred_usb_hub > /dev/null
	if [ $? -ne 0 ]; then
		echo "warning: $preferred_usb_hub module doesn't exist"
	else
	    modprobe $preferred_usb_hub
	    sleep 2
    	lsmod | grep $preferred_usb_hub > /dev/null
		if [ $? -ne 0 ]; then
			echo "couldn't load $preferred_usb_hub module"
		else
			echo "$preferred_usb_hub loaded successfully"
		fi
	fi
fi

case "$mode" in
"LLC_SNAP_RFC1483_BRIDGED_ETH_NO_FCS"|"VCM_RFC_1483_BRIDGED_ETH"|"LLC_RFC1483_ROUTED_IP"|"VCM_RFC1483_ROUTED_IP")
	# load tap/tun module
	echo -e "\nloading TAP/TUN support"
	modprobe -l | grep -E "/tun\." > /dev/null
	if [ $? -ne 0 ]; then
		echo "warning: tun module doesn't exist"
	else
		modprobe tun
		sleep 2
    	lsmod | grep -E "^tun[ \t]" > /dev/null
		if [ $? -ne 0 ]; then
			echo "couldn't load tun module"
		else
			echo "tun loaded successfully"
		fi
	fi
	# verify that /dev/net/tun exists
	if [ ! -c /dev/net/tun ]; then
		echo "/dev/net/tun doesn't exist"
		exit -1
	fi
	;;
esac

# verify if n_hdlc is loaded (module only so, it's safe)
"$BIN_DIR/check-hdlc" > /dev/null
if [ $? -ne 0 ]; then
	lsmod | grep n_hdlc > /dev/null
	if [ $? -ne 0 ]; then
		modprobe -l | grep n_hdlc > /dev/null
		if [ $? -ne 0 ]; then
			echo -e "\nwarning: n_hdlc support not found in kernel config"
		else
    		modprobe n_hdlc
			sleep 1
    		lsmod | grep n_hdlc > /dev/null
			if [ $? -ne 0 ]; then
				echo -e "\ncouldn't load n_hdlc module"
			else
				echo -e "\nn_hdlc loaded successfully"
			fi
		fi
	fi
fi

echo -e "\nloading firmware (2/5)..\n"
# check for the EZ-USB chips. If it's not there, maybe the firmware is
# already loaded ... so continue.
grep "^P:  Vendor=$vid1 ProdID=$pid1" /proc/bus/usb/devices > /dev/null
if [ $? -eq 0 ]; then
    "$BIN_DIR/eci-load1" $eciload1_options
    if [ $? -ne 0 ]; then
        echo "failed to load firmware"
        exit -1
    fi
    echo "firmware loaded successfully"
else
	grep "^P:  Vendor=$vid2 ProdID=$pid2" /proc/bus/usb/devices > /dev/null
	if [ $? -eq 0 ]; then
		echo "firmware seems to be already loaded"
	else
    	echo "modem not found"
    	exit -1
	fi
fi


echo -e "\nsetting up modem (3/5)..\n"
CNT=1
RET=$CNT
while [ $CNT -le $synch_attempts -a $RET -ne 0 ]; do
	"$BIN_DIR/eci-load2" $eciload2_options
	RET=$?
	sleep 1
	CNT=$(expr $CNT + 1)
done
if [ $RET -eq 0 ]; then
	echo "synchronization successful"
else
    echo "failed to get synchronization"
    exit -1
fi

mount | grep devpts > /dev/null
if [ $? -ne 0 ]
then
	echo -e "Mounting devpts filsystem"
	mount -t devpts devpts /dev/pts > /dev/null
	mount | grep devpts > /dev/null
	if [ $? -ne 0 ]
	then
		echo "Devpts failed to mount"
	else
		echo "Devpts mounted correctly"
	fi
fi


GW=""
echo -e "\nconnecting modem (4/5)..\n"
case "$mode" in
"VCM_RFC2364"|"LLC_RFC2364")

	nice --20 pppd call adsl updetach
	if [ $? -ne 0 ]; then
    	echo "failed to connect"
    	exit -1
	fi
	echo "connection successful"

	wait_for_iface ppp0
	GW=ppp0
	;;

"LLC_SNAP_RFC1483_BRIDGED_ETH_NO_FCS"|"VCM_RFC_1483_BRIDGED_ETH")

	$BIN_DIR/pppoeci $pppoeci_options
	if [ $? -ne 0 ]; then
    	echo "failed to connect"
    	exit -1
	fi
	echo "connection successful"

	ifconfig tap0 up
	wait_for_iface tap0
	GW=tap0
	;;

"LLC_RFC1483_ROUTED_IP"|"VCM_RFC1483_ROUTED_IP")

	$BIN_DIR/pppoeci $pppoeci_options
	if [ $? -ne 0 ]; then
    	echo "failed to connect"
    	exit -1
	fi
	echo "connection successful"

	ifconfig tun0 up
	wait_for_iface tun0
	GW=tun0
	;;
*)	echo "unknown PPP mode ($mode), check your driver configuration"
	;;
esac

if [ "$use_dhcp" != "yes" ]
then
	DEV="$GW"
	case "$GW" in
	tap0|tun0)
		if [ "$use_staticip" == "yes" -a -n "$staticip" -a -n "$gateway" ]
		then
			ifconfig $GW $staticip pointopoint $gateway
			GW="gw $gateway"
		else
			echo "couldn't set your static IP or your external gateway"
			echo "if you don't use PPPoE, please check your configuration"
			exit -1
		fi
		;;
	*)	GW="dev $GW"
		;;
	esac

	if [ -n "$GW" ]
	then
		for IFACE in 0 7; do
			route -n | grep -E "[ \t]UG[ \t][ \t0-9\+\-]+eth$IFACE$" > /dev/null
			if [ $? -eq 0 ]; then
				echo "removing existing default route (eth$IFACE).."
				route del default dev eth$IFACE
			fi
		done

		echo "adding default route.."
		route -n | grep -E "[ \t]UG[ \t][ \t0-9\+\-]+$DEV$" > /dev/null
		if [ $? -ne 0 ]; then
			route add default $GW
			if [ $? -ne 0 ]; then
				echo "failed to set default route to $DEV"
			else
				echo "default route added: $DEV"
			fi
		else
			echo "default route to $DEV already exists"
		fi
	fi
fi

exit 0
