#!/bin/sh
# Largely taken from postmarketOS' init functions, many thanks!
# Their repository is licensed under the terms of the GPLv3, same as waitaha.
# https://gitlab.com/postmarketOS/pmaports/-/blob/master/main/postmarketos-initramfs/init_functions.sh

umask 077

start() {
	printf "Configuring USB: "

	mkdir /config
	mount -t configfs -o nodev,noexec,nosuid configfs /config

	CONFIGFS=/config/usb_gadget

	if ! [ -e "$CONFIGFS" ]; then
		echo "SKIP"
		return
	fi

	# Default values for USB-related deviceinfo variables
	usb_idVendor="0x18D1"   # default: Google Inc.
	usb_idProduct="0xD001"  # default: Nexus 4 (fastboot)
	usb_serialnumber="waitaha"
	usb_network_function="ncm.usb0"
	usb_network_function_fallback="rndis.usb0"
	usb_adb_function="ffs.usb0"
	usb_mass_storage_function="mass_storage.0"

	deviceinfo_manufacturer=$(cat /etc/deviceinfo | sed -n 's/.*manufacturer=\([^,]*\)[,]*/\1/p; s/.*manufacturer=\([^,]*\)$/\1/p')
	deviceinfo_name=$(cat /etc/deviceinfo | sed -n 's/.*name=\([^,]*\),codename.*/\1/p')

	# Create an usb gadget configuration
	mkdir $CONFIGFS/g1
	echo "$usb_idVendor"  > "$CONFIGFS/g1/idVendor"
	echo "$usb_idProduct" > "$CONFIGFS/g1/idProduct"
	echo 0x0223 > "$CONFIGFS/g1/bcdDevice"
	echo 0x0200 > "$CONFIGFS/g1/bcdUSB"

	# Create English (0x409) strings
	mkdir $CONFIGFS/g1/strings/0x409 || echo "  Couldn't create $CONFIGFS/g1/strings/0x409"

	echo "$deviceinfo_manufacturer" > "$CONFIGFS/g1/strings/0x409/manufacturer"
	echo "$usb_serialnumber"	> "$CONFIGFS/g1/strings/0x409/serialnumber"
	echo "$deviceinfo_name"		> "$CONFIGFS/g1/strings/0x409/product"

	# Create network function.
	if ! mkdir $CONFIGFS/g1/functions/"$usb_network_function"; then
		echo "  Couldn't create $CONFIGFS/g1/functions/$usb_network_function"
		# Try the fallback function next
		if mkdir $CONFIGFS/g1/functions/"$usb_network_function_fallback"; then
			usb_network_function="$usb_network_function_fallback"
		else
			echo "  Couldn't create $CONFIGFS/g1/functions/$usb_network_function_fallback"
		fi
	fi

	# Create ADB FunctionFS entry
	if ! mkdir $CONFIGFS/g1/functions/"$usb_adb_function"; then
		echo "  Couldn't create $CONFIGFS/g1/functions/$usb_adb_function"
	fi

	# Create mass storage function entry
	if ! mkdir $CONFIGFS/g1/functions/"$usb_mass_storage_function"; then
		echo "  Couldn't create $CONFIGFS/g1/function/$usb_mass_storage_function"
	fi

	# Create configuration instance for the gadget
	mkdir $CONFIGFS/g1/configs/c.1
	mkdir $CONFIGFS/g1/configs/c.1/strings/0x409
	echo "USB networking and storage and ADB" > $CONFIGFS/g1/configs/c.1/strings/0x409/configuration

	i=1
	for disk in $(lsblk -d -I 8 -o KNAME -n); do
		if ! mkdir $CONFIGFS/g1/functions/"$usb_mass_storage_function/lun.$i"; then
			echo "  Couldn't create $CONFIGFS/g1/functions/$usb_mass_storage_function/lun.$i"
		fi
		echo /dev/"$disk" > $CONFIGFS/g1/functions/"$usb_mass_storage_function/lun.$i"/file
		i=$(( i + 1 ))
	done

	# Link the network instance to the configuration
	ln -s $CONFIGFS/g1/functions/"$usb_network_function" $CONFIGFS/g1/configs/c.1

	# Link the ADB function to the configuration
	ln -s $CONFIGFS/g1/functions/"$usb_adb_function" $CONFIGFS/g1/configs/c.1

	# Link the mass storage function to the configuration
	ln -s $CONFIGFS/g1/functions/"$usb_mass_storage_function" $CONFIGFS/g1/configs/c.1

	# Create adb mount point
	mkdir -p /dev/usb-ffs/adb
	# mount -o uid=2000,gid=2000 -t functionfs usb0 /dev/usb-ffs/adb
	mount -t functionfs usb0 /dev/usb-ffs/adb

	adbd &
	sleep 1

	# Check if there's a USB Device Controller
	_udc_dev=$(ls /sys/class/udc)
	if [ -z "$_udc_dev" ]; then
		return
	fi

	# Remove any existing UDC to avoid "write error: Resource busy" when setting UDC again
	if [ "$(wc -w <$CONFIGFS/g1/UDC)" -gt 0 ]; then
		echo "" > $CONFIGFS/g1/UDC || echo "  Couldn't write to clear UDC"
	fi
	# Link the gadget instance to a USB Device Controller. This activates the gadget.
	# See also: https://gitlab.com/postmarketOS/pmbootstrap/issues/338
	echo "$_udc_dev" > $CONFIGFS/g1/UDC

	# Bring up the network interface
	ip addr add 172.16.42.1/24 dev usb0
	ip link set usb0 up

	echo "OK"
}

case "$1" in
  start)
	start
	;;
  *)
	echo "Usage: $0 start"
	exit 1
esac

exit $?
