#!/bin/sh
#
# Copyright (c) 2003 Linuxant inc.
# Copyright (c) 2001-2003 Conexant Systems, Inc.
#
# NOTE: The use and distribution of this software is governed by the terms in
# the file LICENSE, which is included in the package. You must read this and
# agree to these terms before using or distributing this software.
#
# This script handles all aspects of installing and configuring the
# HSF drivers under Linux.  It aspires to be distribution-neutral

load_config()
{
	hsfconf_countryName="AUTO"
	hsfconf_countryT35c=""
	hsfconf_vendorId=""
	hsfconf_deviceId=""
	hsfconf_infFile=""
	hsfconf_firmFile=""
	if [ -f ${hsfetcdir}/config ]; then
		. ${hsfetcdir}/config
	else
		return 0
	fi
}

save_config()
{
	rm -f ${hsfetcdir}/config
	(
		echo "# WARNING: DO NOT EDIT THIS AUTOMATICALLY GENERATED FILE DIRECTLY !"
		echo "# TO PROPERLY CHANGE THE HSF MODEM CONFIGURATION, RUN \"hsfconfig\""
		echo "#"
		echo "hsfconf_countryName=\"${hsfconf_countryName}\""
		echo "hsfconf_countryT35c=\"${hsfconf_countryT35c}\""
		echo "hsfconf_vendorId=\"${hsfconf_vendorId}\""
		echo "hsfconf_deviceId=\"${hsfconf_deviceId}\""
		echo "hsfconf_infFile=\"${hsfconf_infFile}\""
		echo "hsfconf_firmFile=\"${hsfconf_firmFile}\""
	) > ${hsfetcdir}/config
}

show_config()
{
	echo ""
	echo "Current HSF configuration:"
	echo ""
	if [ -n "${hsfconf_countryT35c}" ]; then
		echo "	Country name: \"${hsfconf_countryName}\", T.35 code: `echo \"${hsfconf_countryT35c}\" | ${AWK} -F, '{print $2$1}'`"
	else
		echo "	Country name: \"${hsfconf_countryName}\""
	fi
	echo "	PCI Modem vendor-id: ${hsfconf_vendorId}, device-id: ${hsfconf_deviceId}"
	echo "	Driver inf filename: ${hsfconf_infFile}"
	if [ -n "${hsfconf_firmFile}" ]; then
		echo "	Board firmware file: ${hsfconf_firmFile}"
	fi
}

ask_yesno()
{
	$automode && return $2

	while true; do
		echo -n "$1"
		read answer
		case "${answer}" in
		[yY] | [yY][eE][sS])
			return 0
			;;
		[nN] | [nN][oO])
			return 1
			;;
		"")
			return $2
			;;
		*)
			echo "Enter 'yes' or 'no'"
			;;
		esac
	done
}

find_inf()
{
	_vendor=$1
	_device=$2

	for f in ${hsfinfdir}/*.inf; do

		if [ ! -e "${f}" ]; then
			continue
		fi

		if grep -qi "^PCI\\\\VEN_${_vendor}&DEV_${_device}&" "${f}"; then
			found_inf="${f}"
			return 0
		fi
	done

	return 1
}

check_special_devs()
{
	case "$1:$2" in
	1039:7013)
		# Sis
		echo ""
		echo "DEVICE $1:$2 (Sis AC-Link controller) IS NOT YET SUPPORTED BY THIS DRIVER!"
		echo ""
		echo "Please see http://www.linuxant.com/drivers/hsf/limitations.html"
		sleep 1
		return 1
		;;
	10DE:01C1)
		# Nvidia
		echo ""
		echo "DEVICE $1:$2 (Nvidia AC-Link controller) IS NOT YET SUPPORTED BY THIS DRIVER!"
		echo ""
		echo "Please see http://www.linuxant.com/drivers/hsf/limitations.html"
		sleep 1
		return 1
		;;
	127[aA]:4311 | 14[fF]1:4311)
		# RipTide HSF
		echo ""
		echo "DEVICE $1:$2 IS A RIPTIDE HSF MODEM"
		if [ ! -d ${hsflibdir}/../riptide ]; then
			echo ""
			echo "NOTE: You should also install the RIPTIDE driver in addition to this one"
			echo "Please see http://www.linuxant.com/drivers/riptide"
		fi
		return 0
		;;
	127[aA]:1??? | 14[fF]1:1??? | 127[aA]:2005 | 127[aA]:4321 | 14[fF]1:4321)
		# HCF?
		if [ "$2" = 1025 -o "$2" = 2005 ]; then
			echo ""
			echo "DEVICE $1:$2 MIGHT BE AN HCF MODEM! (both types exist for the same ID)"
			echo "So if it doesn't work with this driver, try the HCF one"
			echo "available from http://www.linuxant.com/drivers"
		fi
		if [ "$2" != 1025 -a "$2" != 2005 -a "$2" != 1631 ]; then
			echo ""
			echo "DEVICE $1:$2 SEEMS TO BE AN HCF MODEM!"
			echo ""
			echo "You might need the HCF driver?"
			echo "Please see http://www.linuxant.com/drivers/modemindent.html"
		fi
		return 0
		;;
	*)
		return 0
		;;
	esac
}

auto_find_inf()
{
	lspci -m -n | \
		${AWK} '-F"' '{print toupper($4)" "toupper($6)}' >/tmp/hsfconfig.pci.$$

	while read vendorid deviceid; do
		if find_inf "${vendorid}" "${deviceid}"; then
			rm -f /tmp/hsfconfig.pci.$$
			return 0
		fi
		check_special_devs "${vendorid}" "${deviceid}"
	done < /tmp/hsfconfig.pci.$$

	rm -f /tmp/hsfconfig.pci.$$
	return 1
}

lspci_text()
{
	if [ -r /proc/pci ]; then
		# First, try to get information directly from /proc/pci, as the kernel
		# usually has more recent pci.ids than the vendor's pciutils
		${AWK}  '
			/Bus.*device.*function.*:/ {
				split($0,pcidev,/[ 	,:]*/);
				printf "%02x:%02x.%x ", pcidev[3],pcidev[5],pcidev[7];
				getline;
				gsub(/^[ 	]*/, "");
				print
			}' </proc/pci
	else
		lspci
	fi
}

choose_device()
{
	if ! ask_yesno "Is the modem presently installed in your system? [yes] " 0; then
		return 1
	fi

	lspci_text | egrep ' ((Communication|Serial) controller|Modem|Class ffff):' > /tmp/hsfconfig.com.$$
	if [ ! -s /tmp/hsfconfig.com.$$ ]; then
		echo ""
		echo "Sorry, no modems were found."
		rm -f /tmp/hsfconfig.com.$$
		return 1
	fi

	while true; do
		echo ""
		${AWK} '{
			sub(/^[0-9a-fA-F:\.][0-9a-fA-F:\.]*.Communication controller: /, "");
			sub(/^[0-9a-fA-F:\.][0-9a-fA-F:\.]*.Serial controller: /, "");
			sub(/^[0-9a-fA-F:\.][0-9a-fA-F:\.]*.Modem: /, "");
			sub(/^[0-9a-fA-F:\.][0-9a-fA-F:\.]*.Class ffff: /, "");
			print NR") "$0;
		}' < /tmp/hsfconfig.com.$$
		notfound="`${AWK} 'END {print NR+1}' < /tmp/hsfconfig.com.$$`"
		echo "${notfound}) None of the above"

		echo ""
		echo -n "Which PCI device is your HSF modem? (1-${notfound}) "
		read answer
		case "${answer}" in
		[0-9] | [0-9][0-9] )
			;;
		*)
			echo "ERROR: Numeric answer between 1 and ${notfound} expected."
			continue
			;;
		esac

		if ! [ "${answer}" -ge 1 -a "${answer}" -le "${notfound}" ]; then
			echo "ERROR: Numeric answer between 1 and ${notfound} expected."
			continue
		fi

		if [ "${answer}" -eq "${notfound}" ]; then
			rm -f /tmp/hsfconfig.com.$$
			return 1
		fi

		pcislot="`sed -n \"${answer} {
			s/ .*//;p
		}\" < /tmp/hsfconfig.com.$$`"

		lspci -m -n -s "${pcislot}" | \
			${AWK} '-F"' '{print toupper($4)" "toupper($6)}' >/tmp/hsfconfig.com.$$

		vendorid=""
		deviceid=""
		read vendorid deviceid </tmp/hsfconfig.com.$$

		rm -f /tmp/hsfconfig.com.$$

		if [ -z "${vendorid}" -o -z "${deviceid}" ]; then
			return 1
		else
			return 0
		fi
	done
}

choose_inf()
{
	ls ${hsfinfdir}/*.inf > /tmp/hsfconfig.infs.$$

	if [ ! -s /tmp/hsfconfig.infs.$$ ]; then
		echo ""
		echo "Sorry, no INF files were found under ${hsfinfdir}."
		rm -f /tmp/hsfconfig.infs.$$
		return 1
	fi

	while true; do
		echo ""
		${AWK} '{print NR") "$0}' < /tmp/hsfconfig.infs.$$
		notfound="`${AWK} 'END {print NR+1}' < /tmp/hsfconfig.infs.$$`"
		echo "${notfound}) None of the above"

		echo ""
		echo -n "Which INF file would you like to use with your HSF modem? (1-${notfound}) "
		read answer

		case "${answer}" in
		[0-9] | [0-9][0-9] )
			;;
		*)
			echo "ERROR: Numeric answer between 1 and ${notfound} expected."
			continue
			;;
		esac

		if ! [ "${answer}" -ge 1 -a "${answer}" -le "${notfound}" ]; then
			echo "ERROR: Numeric answer between 1 and ${notfound} expected."
			continue
		fi

		if [ "${answer}" -eq "${notfound}" ]; then
			rm -f /tmp/hsfconfig.infs.$$
			return 1
		fi

		found_inf="`sed -n \"${answer} {
			s/ .*//;p
		}\" < /tmp/hsfconfig.infs.$$`"

		rm -f /tmp/hsfconfig.infs.$$

		if [ -z "${found_inf}" ]; then
			return 1
		else
			return 0
		fi
	done
}

ask_pci_id()
{
	while true; do
		echo ""
		echo -n "$1"
		read answer
		case "${answer}" in
		[0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F] )
			;;
		*)
			echo "ERROR: 4-digit hexadecimal number expected."
			continue
			;;
		esac

		pci_id="${answer}"
		return 0
	done
}

configure_inf()
{
	found_inf=""
	$automode || echo ""
	if ask_yesno "Should we attempt to automatically configure your hardware? [yes] " 0; then
		if ! auto_find_inf; then
			echo ""
			echo "No supported modem device found."
			if ${automode}; then
				echo "Re-run \"hsfconfig\" manually!"
				return 1
			fi
		fi
	fi

	if [ -z "${found_inf}" ]; then

		if ! choose_device; then
			echo ""
			ask_pci_id "Please enter your modem's PCI Vendor ID [${vendorid}]: "
			vendorid="${pci_id}"
			ask_pci_id "Please enter your modem's PCI Device ID [${deviceid}]: "
			deviceid="${pci_id}"
		fi

		check_special_devs "${vendorid}" "${deviceid}" || return 1

		choose_inf

		if [ -z "${found_inf}" ]; then
			return 1
		fi
	else
		check_special_devs "${vendorid}" "${deviceid}" || return 1
	fi

	hsfconf_infFile="${found_inf}"
	hsfconf_vendorId="${vendorid}"
	hsfconf_deviceId="${deviceid}"

	case "${hsfconf_infFile}" in
	*linux_athens.inf)
		hsfconf_firmFile="${hsfetcdir}/cnxykf.hex"
		;;
	*)
		hsfconf_firmFile=""
		;;
	esac

	echo ""
	echo "Selected PCI VendorID=${vendorid} DeviceID=${deviceid}"
	echo "and INF file ${found_inf}"
}

preprocess_inf()
{
	HSFLINUXVERSION="${hsfversion}" ${AWK} < $1 '{
		while (1) {
			gsub(/\r/, ""); # strip any CRs
			gsub(/;.*$/, ""); # strip comments
			gsub(/^[ 	]*/, ""); # strip leading spaces
			gsub(/[ 	]*$/, ""); # strip trailing spaces
			gsub(/[ 	]*,[ 	]*/, ","); # strip spaces around commas
			gsub(/[ 	]*\\$/, "\\"); # strip spaces before cont. backslashes
			gsub(/[@]HSFLINUXVERSION[@]/, ENVIRON["HSFLINUXVERSION"]);

			if ($0 !~ /\\$/)
				break;

			gsub(/\\$/, ""); # strip continuation backslashes
			prevline=$0;
			getline;
			sub(/^/, prevline); # prepend previous line
		}
		if ($0 != "") # ignore empty lines
			print $0;
	}'
}

get_country_list()
{
	preprocess_inf $1 | \
		${AWK} -F, '
			{ if ($0 !~ /^HKR,Country\\[0-9a-fA-F]*,(NAME|T35CODE)/)
				next;
			}
			{
				sub(/HKR,Country\\/, "");
				gsub(/ /, "_"); # convert spaces to underscores
				gsub(/\"/, ""); # remove double-quotes
			}
			$2 == "T35CODE" {t35code[$1]=$4","$5}
			$2 == "NAME" {name[$1]=$4}
			END { for (x in name)
				if(t35code[x] != "")
					print name[x]" "t35code[x]
			}' | \
		sort
}

rebuild_nvram()
{
	if [ -z "${hsfconf_vendorId}" -o -z "${hsfconf_deviceId}" ]; then
		echo ""
		echo "PCI VendorID and/or DeviceID not configured"
		return 1
	fi

	if [ -z "${hsfconf_countryT35c}" ]; then
		if [ -n "${hsfconf_countryName}" ]; then
			setcountry="${hsfconf_countryName}"
			configure_country
		fi
		if [ -z "${hsfconf_countryT35c}" ]; then
			echo ""
			echo "Country code not configured"
			return 1
		fi
	fi

	(
		echo "HKR,ID,VENDOR,,\"${hsfconf_vendorId}\""
		echo "HKR,ID,DEVICE,,\"${hsfconf_deviceId}\""
		echo "HKR,Country,Current,1,${hsfconf_countryT35c}"

		preprocess_inf ${hsfconf_infFile} | \
			grep '^HKR,' | \
			egrep -vi '^HKR,Country,(Current|Previous),'
	) >/tmp/hsfconfig.inf.$$
	res=$?

	if [ ${res} -eq 0 ]; then
		hsfinf2bin /tmp/hsfconfig.inf.$$ ${hsfnvramf}
		res=$?
	fi

	rm -f /tmp/hsfconfig.inf.$$

	if [ ${res} -eq 0 ]; then
		rm -f ${hsffirmwf}
		if [ -n "${hsfconf_firmFile}" ]; then
			hsffirm2bin "${hsfconf_firmFile}" ${hsffirmwf}
			res=$?
		fi
	fi

	return ${res}
}

ask_country()
{
	get_country_list ${hsfconf_infFile} > /tmp/hsfconf.sup.$$

	while true; do
		if [ -n "${setcountry}" ]; then
			answer="${setcountry}"
			setcountry=""
		elif ${automode}; then
			answer="${country}"
		else
			echo ""
			echo "Supported countries: "
			echo ""

			${AWK} '{
					if (NR != 1) printf ", "
					if (NR % 5 == 0) print ""
					printf "%s",$1
				}
				END { print ""}' </tmp/hsfconf.sup.$$

			echo ""
			echo -n "Please enter your country name [$country]: "
			read answer
			case "${answer}" in
			"" | *"[ 	]"*)
				answer="${country}"
				;;
			*)
				answer="`echo \"${answer}\" | tr '[a-z ]' '[A-Z_]'`"
				;;
			esac
		fi

		if grep -i "^${answer} " /tmp/hsfconf.sup.$$ > /tmp/hsfconf.ncty.$$
		then
			read country countrycode < /tmp/hsfconf.ncty.$$
			rm -f /tmp/hsfconf.sup.$$ /tmp/hsfconf.ncty.$$
			return 0
		else
			echo ""
			echo "ERROR: Country \"${answer}\" is not supported."

			if ${automode}; then
				rm -f /tmp/hsfconf.sup.$$ /tmp/hsfconf.ncty.$$
				return 1
			fi
		fi
	done
}

autodetect_country()
{
	# Try to guess what country we're in, using the timezone settings

	localtime_size="`/bin/ls -lL /etc/localtime 2>/dev/null | ${AWK} '{print $5}'`"

	if ! [ ${localtime_size} -gt 0 ]; then
		return 1
	fi

	zoneinfo_dir=/usr/share/zoneinfo

	if [ ! -d ${zoneinfo_dir} -o ! -f ${zoneinfo_dir}/zone.tab ]; then
		return 1
	fi

	# The following maps ISO-3166 country codes to names used by HSF
	iso_AR='ARGENTINA'
	iso_AU='AUSTRALIA'
	iso_AT='AUSTRIA'
	iso_BE='BELGIUM'
	iso_BG='BULGARIA'
	iso_BH='BAHRAIN'
	iso_BR='BRAZIL'
	iso_CA='CANADA'
	iso_CL='CHILE'
	iso_CN='CHINA'
	iso_HR='CROATIA'
	iso_CZ='CZECH_REPUBLIC'
	iso_DK='DENMARK'
	iso_FI='FINLAND'
	iso_FR='FRANCE'
	iso_DE='GERMANY'
	iso_GR='GREECE'
	iso_HK='HONG-KONG'
	iso_HU='HUNGARY'
	iso_IS='ICELAND'
	iso_IN='INDIA'
	iso_ID='INDONESIA'
	iso_IE='IRELAND'
	iso_IL='ISRAEL'
	iso_IT='ITALY'
	iso_JP='JAPAN'
	iso_KR='KOREA'
	iso_LU='LUXEMBOURG'
	iso_MY='MALAYSIA'
	iso_MX='MEXICO'
	iso_NL='NETHERLANDS'
	iso_NZ='NEW_ZEALAND'
	iso_NO='NORWAY'
	iso_PH='PHILIPPINES'
	iso_PL='POLAND'
	iso_PT='PORTUGAL'
	iso_RU='RUSSIA'
	iso_SG='SINGAPORE'
	iso_SK='SLOVAKIA'
	iso_SI='SLOVENIA'
	iso_ZA='SOUTH_AFRICA'
	iso_ES='SPAIN'
	iso_SE='SWEDEN'
	iso_CH='SWITZERLAND'
	iso_TW='TAIWAN'
	iso_TH='THAILAND'
	iso_TR='TURKEY'
	iso_GB='UK'
	iso_AE='UNITED_ARAB_EMIRATES'
	iso_US='USA'

	(
		cd ${zoneinfo_dir} 2>/dev/null || return 1
		find . -type f -size "${localtime_size}"c -print | sed 's@^\./@@' | \
			while read file; do
				cmp -s /etc/localtime $file || continue
# in the egrep and sed regular expressions below, it is very important to
# have tabs, not spaces
				egrep "	$file(	.*|\$)" ${zoneinfo_dir}/zone.tab
			done | sed -n '/^[^#]/s/	.*//p' | sort | uniq | \
				while read code; do
					eval "echo \${iso_${code}}"
				done | sort | uniq
		return 0
	)
}

configure_country()
{
	# To configure the country type we need an inf file
	if [ -z "${hsfconf_infFile}" ]; then
		echo ""
		echo 1>&2 "$0: configure_country error: no inffile; run hsfconfig -hwtype first."
		return 1
	fi

	country="${setcountry}"
	if [ -z "${country}" -a -n "${hsfconf_countryName}" ]; then
		country="${hsfconf_countryName}"
	fi

	if [ -z "${country}" -o "${country}" = "AUTO" ]; then
		country="`autodetect_country | head -1`"
		echo ""
		if [ -z "${country}" ]; then
			echo "Unable to determine country, defaulting to \"USA\""
			country=USA
		else
			echo "Automatically guessed country (using timezone): \"${country}\""
		fi
		setcountry="${country}"
	fi

	ask_country || return 1

	hsfconf_countryName="${country}"
	hsfconf_countryT35c="${countrycode}"

	echo ""
	echo "Configuring modem for country: \"${hsfconf_countryName}\""
	echo "You can change this setting later with the command \"hsfconfig --country\""
	return 0
}

use_prebuilt_modules()
{
	rm -f "/lib/modules/`uname -r`/misc/hsf"*.o
	if [ ! -d "/lib/modules/`uname -r`/misc" ]; then
		mkdir -p "/lib/modules/`uname -r`/misc"
	fi
	ln -s "${hsflibdir}/modules/binaries/$1/hsf"*.o "/lib/modules/`uname -r`/misc/"
}

files_present()
{
	for f; do
		if [ ! -f "${f}" ]; then
			missing_file="${f}"
			return 1
		fi
	done
}

remove_temp_kernel_tree()
{
	if [ -n "${KERNELORG}" ]; then
		rm -rf "${KERNELSRC}"
		KERNELSRC="${KERNELORG}"
		KERNELORG=""
		return 0
	fi

	return 1
}

create_temp_kernel_tree()
{
	KERNELORG="${KERNELSRC}"
	# get absolute pathname with cd/pwd to ensure that our temp dir
	# is on same filesystem due to use of hardlinks by cp -al
	KERNELSRC="`(cd \"${KERNELORG}\" && /bin/pwd)`-hsftmp$$"
	rm -rf "${KERNELSRC}"
	if ! cp -al "${KERNELORG}/." "${KERNELSRC}"; then
		remove_temp_kernel_tree
		return 1
	fi

	return 0
}

kernelrebuild_instructions()
{
		echo ""
		echo "First, ensure that the proper kernel source and compiler packages"
		echo "from your distribution vendor and/or the community are installed."
		echo ""
		echo "The Linux kernel can then be reconfigured by running \"make menuconfig\""
		echo "under the kernel source directory (usually /usr/src/linux)."
		echo ""
		echo "Verify that the proper options for your system are selected,"
		echo "and that CONFIG_SMP (\"Symmetric multi-processing support\" under"
		echo "\"Processor type and features\") is disabled, as this driver is"
		echo "presently designed to work on single-processor machines."
		echo ""
		echo "Then compile and install your new kernel (for more information about"
		echo "this procedure, see the README file under the kernel source directory),"
		echo "reboot the system using the new kernel, and re-run \"hsfconfig\"."
}

check_kernel()
{
	if [ -r /proc/cpuinfo ] && ! grep -q '^flags[ 	]*:.*mmx' /proc/cpuinfo; then
		echo 1>&2 "HSF drivers require a processor supporting the MMX instruction set."
		return 1
	fi

	if [ -n "$OSKERNSMP" ]; then
		echo 1>&2 ""
		echo 1>&2 "HSF drivers have not been fully tested on SMP kernels."
		echo 1>&2 "Please report results to <hsflinux-bugs@linuxant.com>"
	fi

	return 0
}

right_version_file()
{
	_versionf="$1"

	[ -n "${KERNELVER}" ] || KERNELVER="`uname -r`"

	FILEKERNELVER="`echo UTS_RELEASE | gcc -E -I"${KERNELSRC}/include" -include "${_versionf}" - | grep '^"' | tr -d '"	 '`"

	[ "${KERNELVER}" = "${FILEKERNELVER}" ]
}

recompile_modules()
{
	KERNELVER="`uname -r`"
	KERNELSRC=/usr/src/linux
	KERNELORG=""

	if [ -h /lib/modules/${KERNELVER}/build -a ! -d /lib/modules/${KERNELVER}/build/. ]; then
		echo ""
		echo "ERROR: /lib/modules/${KERNELVER}/build points to a missing directory"
		echo ""
		ls -l /lib/modules/${KERNELVER}/build
		echo ""
		if rpm -qf /lib/modules/${KERNELVER} >/dev/null 2>&1; then
			echo "Please ensure that the kernel-source RPM package is properly installed."
		else
			echo "Please ensure that the kernel-source is properly installed."
		fi
		return 1
	fi

	if [ -d /lib/modules/${KERNELVER}/build/include ]; then
		KERNELSRC=/lib/modules/${KERNELVER}/build
	elif [ ! -d "${KERNELSRC}" -a -d "/usr/local/src/linux" ]; then
		KERNELSRC=/usr/local/src/linux
	fi
	if ! $automode; then
		echo ""
		echo "Where is the linux source build directory that matches your running kernel?"
		echo -n "[${KERNELSRC}] "
		read answer
		case "${answer}" in
		"")
			;;
		*)
			KERNELSRC="${answer}"
			;;
		esac
	fi

	if ! files_present \
		"${KERNELSRC}/include/linux/autoconf.h" \
		"${KERNELSRC}/include/linux/version.h" \
		"${KERNELSRC}/include/linux/modversions.h"; then
		echo ""
		echo "WARNING: missing file ${missing_file}"
		suspect_tree=true
	elif ! right_version_file "${KERNELSRC}/include/linux/version.h"; then
		echo ""
		echo "WARNING: the kernel version (${FILEKERNELVER}) defined in"
		echo "${KERNELSRC}/include/linux/version.h"
		echo "does not match the currently running kernel (${KERNELVER})"
		echo "The cause of this problem is an incorrect kernel source path."
		echo "Please check that ${KERNELSRC} points to the right tree."
		suspect_tree=true
	else
		suspect_tree=false
	fi

	if ${suspect_tree}; then
		echo "The cause of this problem is usually a missing or misconfigured"
		echo "kernel source tree (and sometimes an incorrect directory or symbolic link)."
		# SuSE has copies of autoconf.h and version.h available under /boot
		if [ -d "${KERNELSRC}/include/linux" -a -f /boot/vmlinuz.autoconf.h -a -f /boot/vmlinuz.version.h ] && right_version_file /boot/vmlinuz.version.h && [ -f "${KERNELSRC}/include/linux/modversions.h" ]; then
			echo ""
			echo "However, proper /boot/vmlinuz.{autoconf.h,version.h} were found."
			if ask_yesno "Would you like to try using them (in a temporary kernel tree)? [yes] " 0; then
				if ! create_temp_kernel_tree; then
					echo ""
					echo "Unable to create temporary kernel tree"
					kernelrebuild_instructions
					return 1
				fi
				rm -f "${KERNELSRC}/include/linux/.config" \
						"${KERNELSRC}/include/linux/autoconf.h" \
						"${KERNELSRC}/include/linux/version.h"
				if ! cp -p /boot/vmlinuz.autoconf.h "${KERNELSRC}/include/linux/autoconf.h" || \
					! cp -p /boot/vmlinuz.version.h "${KERNELSRC}/include/linux/version.h"; then
					echo ""
					echo "Unable to copy files to temporary kernel tree"
					remove_temp_kernel_tree
					kernelrebuild_instructions
					return 1
				fi

				# we don't really need .config but it can't hurt if available
				if [ -f /boot/vmlinuz.config ]; then
					cp -p /boot/vmlinuz.config "${KERNELSRC}/include/linux/.config"
				fi
			fi
		fi
	fi

	# are we ok now?
	if [ ! -f "${KERNELSRC}/include/linux/version.h" \
			-o ! -f "${KERNELSRC}/include/linux/autoconf.h" \
			-o ! -f "${KERNELSRC}/include/linux/modversions.h" ]; then
		remove_temp_kernel_tree
		kernelrebuild_instructions
		return 1
	fi

	recomplogf=/tmp/hsfconfig-buildlog.txt

	# set FILEKERNELVER if it isn't already
	[ -n "${FILEKERNELVER}" ] || right_version_file "${KERNELSRC}/include/linux/version.h"

	echo ""
	echo "Re-compiling HSF modules for kernel ${FILEKERNELVER}, using source directory"
	echo "${KERNELSRC}. Please wait.."

	(cd ${hsflibdir}/modules && make "KERNELSRC=${KERNELSRC}" clean minstall) \
		> ${recomplogf} 2>&1

	res=$?

	(cd ${hsflibdir}/modules && make "KERNELSRC=${KERNELSRC}" clean) >/dev/null 2>&1

	remove_temp_kernel_tree

	if [ $res -eq 0 ]; then
		rm -f ${recomplogf}
		echo "Re-compilation and installation of HSF modules succeeded."
		return 0
	else
		echo ""
		echo "ERROR: Module re-compilation and installation failed!"
		echo "Please examine the log file \"${recomplogf}\" to determine why."
		return 1
	fi
}

modules_exist()
{
	files_present "/lib/modules/`uname -r`/misc/hsf"*.o
}

hsfscrdmp_exists()
{
	files_present "/lib/modules/`uname -r`/misc/hsfscrdmp.o"
}

remove_kernel_modules()
{
	if modules_exist; then
		echo ""
		echo "Removing HSF drivers from /lib/modules/`uname -r`/misc/"
		rm -f "/lib/modules/`uname -r`/misc/hsf"*.o
	fi
	return 0
}

binary_modules_avail()
{
	[ -d "${hsflibdir}/modules/binaries/$1" ]
}

choose_kernel()
{
	if modules_exist; then
		echo ""
		echo "Warning: existing HSF modules found under /lib/modules/`uname -r`/misc/"
		if ask_yesno "Would you like to keep using them? [no] " 1; then
			return 0
		fi
	fi

	chosen_binary_modules=""
	if binary_modules_avail "${OSKERNTYPE}/${OSDISTIDNT}/${OSKERNNAME}-${OSKERNVERS}${OSKERNSMP}"; then
		chosen_binary_modules="${OSKERNTYPE}/${OSDISTIDNT}/${OSKERNNAME}-${OSKERNVERS}${OSKERNSMP}"
	fi

	if [ -n "${chosen_binary_modules}" ]; then
		echo ""
		echo "Pre-built HSF modules that seem compatible with your system were found under"
		echo "${hsflibdir}/modules/binaries/${chosen_binary_modules}."

		if ask_yesno "Would you like to use them? [yes] " 0; then
			if use_prebuilt_modules "${chosen_binary_modules}"; then
				return 0
			fi
		fi
	else
		echo ""
		echo "This package does not contain pre-built modules suitable for your system:"
		echo "	Distribution: ${OSDISTNAME}-${OSDISTVERS}"
		echo "	Kernel arch: ${OSKERNTYPE}${OSKERNSMP}"
		echo "	Kernel version: ${OSKERNNAME}-${OSKERNVERS}"
	fi

	if [ -f ${hsflibdir}/modules/makefile ]; then
		echo ""
		echo "Trying to automatically re-compile the modules.."
		echo "(this requires a C compiler and proper kernel sources to be installed)"

		if recompile_modules; then
			return 0
		fi
	else
		echo ""
		echo "Please obtain the appropriate variant of this package for your system"
		echo "or try the generic RPM or tar version."
	fi

	return 1
}

choose_major()
{
	device=$1
	shift

	first=240
	max=250

	major=${first}

	while [ ${major} -ne ${max} ]; do
		excluded=false
		for exclude in $*; do
			if [ ${major} -eq ${exclude} ]; then
				excluded=true
				break
			fi
		done

		if ! ${excluded} && \
			! grep -q "^ *${major} " /proc/devices && \
			! sed -e 's/#.*//g' -e '/hsfserial/d' -e '/hsfscrdmp/d' ${modulesconf} | grep -q "^alias[ 	][ 	]*char-major-${major}"
			then
				break
		fi

		major="`expr ${major} + 1`"
	done

	if [ ${major} -ne ${max} ]; then
		echo ${major}
		return 0
	else
		echo 1>&2 "$0: Cannot find major device number for ${device} in range ${first}-${max}"
		return 1
	fi
}

devfsd_running()
{
	ps -e | grep -q 'devfsd$'
}

unconfigure_serial()
{
	if [ -f /etc/modutils/hsf ]; then
		rm -f /etc/modutils/hsf
		update-modules
	elif [ -f /etc/modules.d/hsf ]; then
		rm -f /etc/modules.d/hsf
		update-modules
	else
		if sed -e '/^alias.*hsfserial/d' -e '/^options.*hsfserial/d' \
				-e '/^alias.*hsfscrdmp/d' -e '/^options.*hsfscrdmp/d' \
		< ${modulesconf} > ${modulesconf}.$$; then
			cp ${modulesconf}.$$ ${modulesconf}
		fi

		rm -f ${modulesconf}.$$ ${outmodulesconf}
	fi

	if [ -f /etc/devfs/conf.d/hsf.conf ]; then
		rm -f /etc/devfs/conf.d/hsf.conf
		[ -x /usr/sbin/update-devfsd ] && update-devfsd
		killall -HUP devfsd 2>/dev/null
	else
		if [ -f /etc/devfsd.conf ]; then
			if sed -e '/REGISTER.*ttyS*HSF/d' -e '/^LOOKUP.*ttySHSF/d' \
					< /etc/devfsd.conf > /etc/devfsd.conf.$$; then
				cp /etc/devfsd.conf.$$ /etc/devfsd.conf
			fi
			rm -f /etc/devfsd.conf.$$
			killall -HUP devfsd 2>/dev/null
		fi
	fi

	ttydevicename=/dev/ttySHSF0
	cuadevicename=/dev/cuaHSF0

	if ! devfsd_running; then
		rm -f ${ttydevicename} ${cuadevicename}
	fi

	if [ -h /dev/modem -a "`/bin/ls -l /dev/modem 2>/dev/null | ${AWK} '{print $11}'`" = ${ttydevicename} ]; then
		rm -f /dev/modem
	fi
}

configure_serial()
{
	hsftty_major="`choose_major hsfserial`"

	if [ -z ${hsftty_major} ]; then
		exit 1
	fi

	hsfcua_major="`choose_major hsfserial_callout ${hsftty_major}`"
	if [ -z ${hsfcua_major} ]; then
		exit 1
	fi

	if hsfscrdmp_exists; then
		scrdevicename=/dev/hsfscr
		dmpdevicename=/dev/hsfdmp

		hsfscrdmp_major="`choose_major hsfscrdmp ${hsftty_major} ${hsfcua_major}`"
		if [ -z ${hsfscrdmp_major} ]; then
			exit 1
		fi
	fi

	if [ -d /etc/modutils -a -x /sbin/update-modules ]; then
		# Debian
		runupdatemodules=true
		outmodulesconf=/etc/modutils/hsf
	elif [ -d /etc/modules.d -a -x /usr/sbin/update-modules ]; then
		# Gentoo
		runupdatemodules=true
		outmodulesconf=/etc/modules.d/hsf
	else
		runupdatemodules=false
		outmodulesconf=/tmp/hsfmodconf.$$
	fi

	(
		echo "alias /dev/ttySHSF* hsfserial"
		echo "alias char-major-${hsftty_major} hsfserial"

		echo "alias /dev/ttyCUA* hsfserial"
		echo "alias char-major-${hsfcua_major} hsfserial"
		echo "alias /dev/modem hsfserial"
		echo "options hsfserial serialmajor=${hsftty_major} calloutmajor=${hsfcua_major}"

		[ -n "${scrdevicename}" ] && echo "alias ${scrdevicename} hsfscrdmp"
		[ -n "${dmpdevicename}" ] && echo "alias ${dmpdevicename} hsfscrdmp"
		if [ -n "${hsfscrdmp_major}" ]; then
			echo "alias char-major-${hsfscrdmp_major} hsfscrdmp"
			echo "options hsfscrdmp scrdmpmajor=${hsfscrdmp_major}"
		fi
	) > ${outmodulesconf}

	if ${runupdatemodules}; then
		update-modules
	else
		if (
			sed -e '/^alias.*hsfserial/d' -e '/^options.*hsfserial/d' \
				-e '/^alias.*hsfscrdmp/d' -e '/^options.*hsfscrdmp/d'

			cat ${outmodulesconf}

		) < ${modulesconf} > ${modulesconf}.$$; then
			if ! cp ${modulesconf}.$$ ${modulesconf}; then
				rm -f ${modulesconf}.$$ ${outmodulesconf}
				exit 1
			fi
		fi

		rm -f ${modulesconf}.$$ ${outmodulesconf}
	fi

	depmod -e -a

	ttydevicename=/dev/ttySHSF0
	cuadevicename=/dev/cuaHSF0

	if [ -d /etc/devfs/conf.d ]; then
		# we use nice to bypass the stupid check in devfsd (Hi Richard!)
		# that prevents direct execution of modprobe (in favor of MODLOAD,
		# which unfortunately doesn't provide a way to specify a module
		# name other than the device itself and under Mandrake at least,
		# the ttyS* alias in /etc/modules.devfs overrides our own alias
		# in modules.conf)
		echo 'LOOKUP	^(ttySHSF|modem$) EXECUTE nice /sbin/modprobe hsfserial
REGISTER	^ttySHSF0$ CFUNCTION GLOBAL symlink $devname modem
UNREGISTER	^ttySHSF0$ CFUNCTION GLOBAL unlink modem' \
			> /etc/devfs/conf.d/hsf.conf
		rm -f /dev/modem
		[ -x /usr/sbin/update-devfsd ] && update-devfsd
		killall -HUP devfsd 2>/dev/null
	else
		if [ -f /etc/devfsd.conf ]; then
			if (
				sed -e '/REGISTER.*ttyS*HSF/d' -e '/^LOOKUP.*ttySHSF/d'
				echo 'LOOKUP	^(ttySHSF|modem$) EXECUTE nice /sbin/modprobe hsfserial
REGISTER	^ttySHSF0$ CFUNCTION GLOBAL symlink $devname modem
UNREGISTER	^ttySHSF0$ CFUNCTION GLOBAL unlink modem'
			) < /etc/devfsd.conf > /etc/devfsd.conf.$$; then
				cp /etc/devfsd.conf.$$ /etc/devfsd.conf
			fi
			rm -f /etc/devfsd.conf.$$
			rm -f /dev/modem
			killall -HUP devfsd 2>/dev/null
		fi
	fi

	if ! devfsd_running; then
		hsf_minor=64

		rm -f ${ttydevicename} ${cuadevicename}

		if [ -n "${scrdevicename}" ]; then
			rm -f ${scrdevicename}
			mknod -m 600 ${scrdevicename} c ${hsfscrdmp_major} 0 || exit 1
		fi

		if [ -n "${dmpdevicename}" ]; then
			rm -f ${dmpdevicename}
			mknod -m 600 ${dmpdevicename} c ${hsfscrdmp_major} 1 || exit 1
		fi

		mknod -m 666 ${ttydevicename} c ${hsftty_major} ${hsf_minor} || exit 1
		mknod -m 666 ${cuadevicename} c ${hsfcua_major} ${hsf_minor} || exit 1

		if [ -h /dev/modem -a "`/bin/ls -l /dev/modem 2>/dev/null | ${AWK} '{print $11}'`" = ${ttydevicename} ]; then
			rm -f /dev/modem
		fi

		if [ -e /dev/modem ]; then
			if ! fuser /dev/modem >/dev/null 2>&1; then
				rm -f /dev/modem.old
				mv /dev/modem /dev/modem.old

				echo "WARNING: renamed existing /dev/modem to /dev/modem.old:"
				echo ""
				/bin/ls -l /dev/modem.old
			fi
		fi

		if [ ! -e /dev/modem ]; then
			ln -s ${ttydevicename} /dev/modem
		fi
	fi

	echo ""
	echo "Your HSF modem should now be accessible as ${ttydevicename}"

	if [ -h /dev/modem -a "`/bin/ls -l /dev/modem 2>/dev/null | ${AWK} '{print $11}'`" = ${ttydevicename} ]; then
		echo "or through the symbolic link /dev/modem."
	fi

	echo ""

	oldnames="/dev/cnxt0 /dev/hsf0"

	for oldname in ${oldnames}; do
		if [ -e ${oldname} ]; then
			echo "WARNING: old device ${oldname} still exists; you should probably remove it"
		fi
	done
}

identify_system()
{
	OSDISTNAME=unknown
	OSDISTIDNT=unknown
	OSDISTVERS=unknown

	if [ -f /etc/debian_version ]; then
		OSDISTNAME=Debian
		OSDISTIDNT=deb
		read OSDISTVERS < /etc/debian_version
	elif [ -f /etc/slackware-version ]; then
		OSDISTNAME=Slackware
		OSDISTIDNT=slack
		OSDISTVERS="`${AWK} '{print $1; exit}' /etc/slackware-version`"
	elif [ -f /etc/conectiva-release ]; then
		OSDISTNAME=Conectiva
		OSDISTIDNT=conectiva
	elif [ -f /etc/SuSE-release ]; then
		OSDISTNAME=SuSE
		OSDISTIDNT=suse
		OSDISTVERS="`sed -n '/^VERSION/s/^.*=[ 	]*//p' < /etc/SuSE-release`"
	elif [ -f /etc/mandrake-release ]; then
		OSDISTNAME=Mandrake
		OSDISTIDNT=mdk
	#it would be better to use rpm instead of sed but it doesn't work
	#recursively (due to database locking) when this script is called during
	#the package's installation
	#	OSDISTVERS="`rpm -q --queryformat '%{VERSION}\n' mandrake-release | sort -r | head -1`"
		OSDISTVERS="`sed -n '/release /{s/^.*release  *\([^ ]*\)/\1/;s/ .*//;p;q;}' < /etc/mandrake-release`"
	#elif [ -f /etc/yellowdog-release ]; then
	#	OSDISTNAME=YellowDog
	elif [ -f /etc/redhat-release ]; then
		OSDISTNAME=RedHat
		OSDISTIDNT=rh
		OSDISTVERS="`sed -n '/release /{s/^.*release  *\([^ ]*\)/\1/;s/ .*//;p;q;}' < /etc/redhat-release`"
	elif [ -d /var/lib/LST ]; then
		OSDISTNAME=Caldera
		OSDISTIDNT=caldera
	fi

	OSKERNNAME="`uname -s | tr '[A-Z]' '[a-z]'`"
	OSKERNARCH="`uname -m`"
	if [ -r /boot/kernel.h ]; then
		OSKERNTYPE="`sed -n '/^#define[ 	]__MODULE_KERNEL_/s/^#define[ 	]__MODULE_KERNEL_\([^ 	]*\)[ 	]*.*/\1/p' </boot/kernel.h`"
	fi
	if [ -z "${OSKERNTYPE}" ]; then
		OSKERNTYPE="${OSKERNARCH}"
	fi
	OSKERNVERS="`uname -r`"

	if uname -v | grep -q SMP; then
		OSKERNSMP="-SMP"
	else
		OSKERNSMP=""
	fi

	if [ -r /proc/ksyms -a `grep -c '_R[a-f0-9]*$' /proc/ksyms` -gt 100 ]; then
		OSKERNMODV="-MODVERS"
	else
		OSKERNMODV=""
	fi

	echo "$OSKERNNAME-$OSKERNARCH($OSKERNTYPE)-$OSKERNVERS$OSKERNSMP$OSKERNMODV $OSDISTNAME-$OSDISTVERS"
}

dump_cmd()
{
	echo ""
	echo "${dumpprefix} $*"
	$@
}

dump_file()
{
	dump_cmd cat -v $@
}

dump_diagnostics()
{
	dumpprefix="+"

	> "${hsfdiagfile}" || return $?

	if ! ${noprobe}; then
		echo ""
		echo "Probing \"hsfserial\" module..."
		(
			dump_cmd modprobe -v hsfserial
			dump_cmd lsmod
		) >> "${hsfdiagfile}" 2>&1
	fi

	echo ""
	echo "Dumping system diagnostic information..."

	case "${hsfdiagfile}" in
	*longdiag*)
		longdiag=true
		;;
	*)
		longdiag=false
		;;
	esac

	(
		dump_cmd date
		dump_cmd $0 --info
		dump_cmd identify_system
		dump_cmd uname -a

		dump_cmd gcc -v

		dump_file /proc/version
		dump_file /proc/cpuinfo

		for f in /etc/*_version /etc/*-version /etc/*-release; do
			if [ -r "${f}" ]; then
				dump_file "${f}"
			fi
		done

		dump_cmd lspci -n
		dump_cmd lspci -v
		dump_cmd lspci -n -vvv

		for p in pci cmdline uptime \
			devices misc filesystems interrupts \
			iomem ioports dma mtrr \
			partitions mounts swaps meminfo \
			stat apm modules ldiscs
		do
			dump_file /proc/${p}
		done

		dump_cmd modprobe -V
		dump_cmd modprobe -l "*hsfserial*"
		dump_file "${modulesconf}"
		dump_cmd depmod -e -a

		dump_file /proc/tty/drivers
		for f in /proc/tty/driver/*; do
			if [ -r "${f}" ]; then
				dump_file "${f}"
			fi
		done

		dump_cmd ls -l '/dev/modem*'
		dump_cmd ls -l '/dev/*HSF*'
		dump_cmd ls -l '/dev/*cnxt*'
		dump_cmd ls -l '/dev/*hsf*'
		dump_cmd ls -l '/dev/ttyS*'
		dump_cmd ls -l '/dev/tts*'

		dump_cmd ls -lR "${hsflibdir}/."

		if ${longdiag}; then
			for p in slabinfo ksyms
			do
				dump_file /proc/${p}
			done

			dump_file /lib/modules/`uname -r`/build/.config
			dump_file /lib/modules/`uname -r`/build/include/linux/version.h
			dump_file /lib/modules/`uname -r`/build/include/linux/autoconf.h
			dump_file /lib/modules/`uname -r`/build/include/linux/autoconf-up.h
			dump_file /lib/modules/`uname -r`/build/include/linux/rhconfig.h
			dump_file /lib/modules/`uname -r`/build/include/linux/modules/ksyms.ver

			dump_file /boot/vmlinuz.version.h
			dump_file /boot/vmlinuz.autoconf.h
			dump_file /boot/vmlinuz.config

			dump_file /boot/kernel.h

			dump_cmd ls -lR /etc/.
			dump_cmd ls -lR /lib/modules/.
			dump_cmd ls -lR /boot/.

			dump_cmd ls -l /usr/src/linux/include/.
			dump_cmd ls -l /usr/src/linux/include/linux/.
			dump_cmd ls -l /usr/src/linux/include/asm-i386/.
			dump_cmd ls -l /usr/include/. /usr/src/.

			dump_cmd env

			dump_cmd ps -efw

			dump_cmd sh --version
			dump_cmd sed --version
			dump_cmd ${AWK} --version
			dump_cmd printf --version

			dump_cmd tar --version

			dump_cmd rpm --version
			dump_cmd rpm --showrc
			dump_cmd rpm --query --all
		fi

		dump_cmd dmesg
		if dmesg | grep -qi 'panic'; then
			dump_cmd dmesg | ksymoops
		fi

	) >> "${hsfdiagfile}" 2>&1

	if [ -f "${hsfdiagfile}" ]; then
		echo ""
		echo "System diagnostic information has been saved to the file:"
		echo ""
		ls -l ${hsfdiagfile}
		echo ""
		echo "As it could contain private information about this system, we recommend that"
		echo "you verify its contents before sending it to third parties."
	fi
}

show_intro()
{
	echo "Linux HSF softmodem drivers, version ${hsfversion}"

	case "${hsfversion}" in
	*beta*)
		(
		echo ""
		echo "WARNING: this is an EXPERIMENTAL BETA VERSION of the HSF drivers for Linux."
		echo "USE AT YOUR OWN RISK! See the file ${hsflibdir}/LICENSE for details."
		) 1>&2
		;;
	esac

	case "${hsfversion}" in
	*lnxt*)
		(
		echo ""
		echo "Conexant Systems neither distributes nor maintains this package."
		echo "PLEASE DO NOT CONTACT CONEXANT REGARDING THIS SOFTWARE!!!"
		echo ""
		echo "If you require assistance or need more information, go to:"
		echo "              http://www.linuxant.com/drivers"
		echo ""
		echo "When reporting a problem for the first time, please send"
		echo "us the file generated by \"hsfconfig --dumpdiag\"."
		) 1>&2
		;;
	esac
}


show_usage_and_exit()
{
	show_intro

	cat 1>&2 << EOT

Usage: `basename $0` [options]

  -t, --hwtype                 Configure hardware type and parameters
  -c, --country[=<name>]       Configure country, to <name> if specified
                               (Use country name "auto" to infer from timezone)
  -k, --kernel                 Configure and install HSF kernel modules
  -s, --serial                 Install HSF serial port devices

  -n, --nvram                  Rebuild ${hsfnvramf} using current config

  -i, --info                   Show current configuration parameters

  -d, --dumpdiag[=<file>]      Probe driver modules and dump system diagnostic
                               information to <file>
                               (default: ${hsfdiagfile})

  -N, --noprobe                Do dumpdiag without probing modules (safer)

  -a, --auto                   Run in automatic mode, without prompting user
  -r, --remove                 Remove HSF devices and kernel modules

  -h, --help                   This small usage guide
  -V, --version                Show HSF version

Default options if none selected: --kernel --hwtype --country --serial
EOT
	exit 1
}

# end of functions; execution starts here

PATH=/usr/sbin:/sbin:/usr/bin:/bin:/usr/local/sbin:/usr/local/bin
export PATH

umask 022

hsflibdir="/usr/lib/hsf"
hsfetcdir="/etc/hsf"
hsfinfdir="/etc/hsf/inf"
hsfnvramf="/etc/hsf/nvram.bin"
hsffirmwf="/etc/hsf/firmware.bin"
hsfversion="5.03.27lnxtbeta03042700"

hsfdiagfile="/tmp/hsfdiag.txt"

if [ -f /etc/modules.conf ]; then
	modulesconf=/etc/modules.conf
elif [ -f /etc/conf.modules ]; then
	modulesconf=/etc/conf.modules
fi

TEMP=`getopt -a -o tc::ksnid::NarhV --long hwtype,country::,kernel,serial,nvram,info,dumpdiag::,noprobe,auto,remove,help,version -n "\`basename $0\`" -- "$@"`
if [ $? != 0 ]; then
	show_usage_and_exit
fi

eval set -- "$TEMP"

automode=false
noprobe=false
do_cfghwtype=false
do_cfgnvram=false
do_cfgkernel=false
do_cfgserial=false
do_infocfg=false
do_dumpdiag=false
do_cfgremove=false
do_cfgcountry=false
setcountry=""
setdiagfile=""

if which gawk >/dev/null 2>&1; then
	AWK=gawk
else
	AWK=awk
fi

explicitopt=false

while true ; do
	case "$1" in
		-a|--auto) automode=true; shift ;;
		-c|--country)
			explicitopt=true
			do_cfgcountry=true
			if [ -n "$2" ]; then
				setcountry="`echo \"$2\" | tr '[a-z ]' '[A-Z_]'`"
			fi
			shift 2
			;;
		-t|--hwtype) explicitopt=true; do_cfghwtype=true; shift ;;
		-n|--nvram)  explicitopt=true; do_cfgnvram=true;  shift ;;
		-k|--kernel) explicitopt=true; do_cfgkernel=true; shift ;;
		-s|--serial) explicitopt=true; do_cfgserial=true; shift ;;
		-i|--info)   explicitopt=true; do_infocfg=true; shift ;;
		-d|--dumpdiag)
			explicitopt=true
			do_dumpdiag=true
			setdiagfile="$2"
			shift 2
			;;
		-N|--noprobe)
			explicitopt=true
			do_dumpdiag=true
			noprobe=true
			shift
			;;
		-r|--remove) explicitopt=true; do_cfgremove=true; shift ;;
		-h|--help) show_usage_and_exit; shift ;;
		-V|--version) echo "${hsfversion}"; exit 0;;
		--) shift ; break ;;
		*) echo "Internal error!" ; exit 1 ;;
	esac
done

# Accomodate --country <name> as equivalent to --country=<name>
if ${do_cfgcountry} && [ $# -ge 1 -a -z "${setcountry}" ]; then
	setcountry="`echo \"$1\" | tr '[a-z ]' '[A-Z_]'`"
	shift
fi

# Accomodate --dumpdiag <file> as equivalent to --dumpdiag=<file>
if ${do_dumpdiag} && [ $# -ge 1 -a -z "${setdiagfile}" ]; then
	setdiagfile="$1"
	shift
fi

if [ $# -ne 0 ]; then
	echo 1>&2 "$0: extraneous arguments: $*"
	show_usage_and_exit
fi

# If nothing explicitely specified, configure everything
if ! ${explicitopt}; then
	do_cfghwtype=true
	do_cfgcountry=true
	do_cfgkernel=true
	do_cfgserial=true
fi

if ! ${do_cfgremove}; then
	show_intro
fi

# before doing anything, try to unload any hsf drivers possibly running
hsfstop >/dev/null 2>&1

identify_system >/dev/null

load_config || exit $?

if ${do_cfgremove}; then
	remove_kernel_modules || exit $?
	unconfigure_serial || exit $?
fi

if ${do_cfghwtype}; then
	configure_inf || exit $?
	do_cfgnvram=true
fi

if ${do_cfgcountry}; then
	configure_country || exit $?
	do_cfgnvram=true
fi

if ${do_cfgnvram}; then
	rebuild_nvram || exit $?
	save_config || exit $?
fi

if ${do_cfgkernel}; then
	check_kernel || exit $?
	choose_kernel || exit $?
fi

if ${do_cfgserial}; then
	configure_serial || exit $?
fi

if ${do_infocfg}; then
	show_config || exit $?
fi

if ${do_dumpdiag}; then
	if [ -n "${setdiagfile}" ]; then
		hsfdiagfile="${setdiagfile}"
	fi
	dump_diagnostics || exit $?
fi
