#!/bin/sh
#
# Copyright (c) 2008 Janne Kataja <janne.kataja@iki.fi>
# Copyright (c) 2008 Nokia Corporation <integration@maemo.org>
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA

# Return codes
# 0: OK
# 1: Script must be run as user root
# 2: USB mode is not writable
# 3: USB gadget drivers not found
# 4: Interface usb0 not listed in /etc/network/interfaces
# 5: USB port in use
# 6: insmod failed

NAME=usb-helper
G_ETHER=/mnt/initfs/lib/modules/`uname -r`/g_ether.ko
G_STORAGE=/mnt/initfs/lib/modules/`uname -r`/g_file_storage.ko
G_STORAGE_OPTS="stall=0 luns=2 removable"
USB_MODE=/sys/devices/platform/musb_hdrc/mode
IAP_NAME=USB

# Show command usage
usage() {
	cat <<END
Usage: $NAME [ACTION]
Helper program for changing USB device mode

Action must be one of:
	network	RNDIS/Ethernet networking device
	storage	File storage device
	host	Host mode
	test	Test if USB port is in use

END
}

# Delay to let kernel do it's magic
yield() {
	sleep 1
}

# Change USB port mode
usb_mode() {
	echo "$1" > $USB_MODE
	yield
}

# Unload any existing gadget drivers
unload() {
	if grep -q g_file_storage /proc/modules ; then
		rmmod g_file_storage
		if [ $? != 0 ] ; then
			echo "$NAME: rmmod exited with failure"
		fi
	elif grep -q g_ether /proc/modules ; then
		rmmod g_ether
		if [ $? != 0 ] ; then
			echo "$NAME: rmmod exited with failure"
		fi
	fi
	yield
	return 0
}

# Test if USB interface is already in use
# Rules from hald-addon-usb-cable
test_usb() {
	if egrep -q "(a_host|a_suspend|b_peripheral)" $USB_MODE ; then
		return 1
	fi
	return 0
}

# Interface usb0 is listed in /etc/network/interfaces
have_usb0() {
	grep -v "^#" /etc/network/interfaces | grep -q "usb0"
	return $?
}

# Start RNDIS/Ethernet networking device
run_insmod() {
	/sbin/insmod $1 $2
	if [ $? != 0 ] ; then
		echo "$NAME: insmod exited with failure"
		return 1
	fi
	return 0
}

# Run sanity checks
if [ `id -u` != 0 ] ; then
	echo "$NAME: script must be run as user root"
	exit 1
fi

if ! [ -w $USB_MODE ] ; then
	echo "$NAME: USB mode is not writable"
	exit 2
fi

if ! [ -r $G_ETHER -a -r $G_STORAGE ] ; then
	echo "$NAME: USB gadget drivers not found"
	exit 3
fi

if ! have_usb0 ; then
	echo "$NAME: Interface usb0 not listed in /etc/network/interfaces"
	exit 4
fi

if ! test_usb ; then
	echo "$NAME: USB port in use"
	exit 5
fi

# Commands
case "$1" in
	# Just run the sanity checks
	test)
		;;

	# Change to USB host mode
	host)
		# Take usb0 interface down
		if /sbin/ifconfig usb0 2>/dev/null | grep -q UP ; then
			/sbin/ifdown usb0
		fi
		# Remove dummy entry for connectivity
        	su user -c "gconftool-2 -u /system/osso/connectivity/IAP/${IAP_NAME}/type"
		unload
		usb_mode host
		;;
	# Change to USB peripheral mode and load storage gadget
	storage)
		# Take usb0 interface down
		if /sbin/ifconfig usb0 2>/dev/null | grep -q UP ; then
			/sbin/ifdown usb0
		fi
		# Remove dummy entry for connectivity
        	su user -c "gconftool-2 -u /system/osso/connectivity/IAP/${IAP_NAME}/type"
		# Change to OTG mode
		if grep -q "host" $USB_MODE ; then
			usb_mode otg
		fi
		# Remove g_ether module
		if ! grep -q "g_file_storage" /proc/modules ; then
			unload
		fi
		# Insert module
		if ! run_insmod $G_STORAGE "$G_STORAGE_OPTS" ; then
			exit 6
		fi
		# Run insmod again if module insertion failed
		if ! grep -q "g_file_storage" /proc/modules ; then
			if ! run_insmod $G_STORAGE "$G_STORAGE_OPTS" ; then
				exit 6
			fi
		fi
		;;
	# Change to USB peripheral mode, load network gadget and start daemon
	network)
		# Remove g_ether module
		if ! grep -q "g_ether" /proc/modules ; then
			unload
		fi
		if grep "host" $USB_MODE ; then
			usb_mode otg
		fi
		if ! run_insmod $G_ETHER ; then
			exit 6
		fi
		# Run insmod again if module insertion failed
		if ! grep -q "g_ether" /proc/modules ; then
			if ! run_insmod $G_ETHER ; then
				exit 6
			fi
		fi
		# Take usb0 interface up
		/sbin/ifup usb0
		# Add dummy entry for connectivity
	        su user -c "gconftool-2 -t string -s /system/osso/connectivity/IAP/${IAP_NAME}/type DUMMY"
		;;
	# Show usage
	*)
		usage
		;;
esac

exit 0
