#!/bin/sh
#
# PROVIDE: maudio
# REQUIRE: LOGIN
# KEYWORD: nojail
#
# Add the following lines to /etc/rc.conf.local or /etc/rc.conf
# to enable this service:
#
# maudio_enable (bool):	Set to NO by default.
#			Set it to YES to enable maudio.
# Usage:
#	maudio start [<device> <product id>]	# load firmware to device with specified product ID

# disable at boot time and prevent simultaneous runs
if [ -n "${_boot}" -o -f /var/run/maudio.pid ]; then
	exit 0
fi
trap "rm -f /var/run/maudio.pid" 1 2 10 13 14 15 EXIT
echo $$ >/var/run/maudio.pid

. /etc/rc.subr

name="maudio"
rcvar=maudio_enable
load_rc_config $name

: ${maudio_enable="NO"}
: ${maudio_default="NO"}

command="/usr/local/bin/dfu-util"
start_cmd="maudio_start"
firmware_dir="/usr/local/share/maudio"
temp_dir="/tmp/.maudio"
required_modules="uhub/uaudio"
required_dirs=$firmware_dir
required_files=$command
extra_commands="attach detach"
attach_cmd="maudio_attach"
detach_cmd="maudio_detach"

maudio_start()
{
	local firmware dev idVendor idProduct

	mkdir -p ${temp_dir} && touch ${temp_dir}/state

	if [ -n "${1}" -a -n "${2}" ]; then
		idProduct=${2}
		dev=${1}
	else
		for dev in /dev/ugen*; do
			dev=${dev#/dev/*}
			eval $( /usr/sbin/usbconfig -d ${dev} dump_device_desc \
				|grep -E "idVendor = 0x0763|idProduct = 0x280[34568]" |tr -d " " )
			if [ -n "${idVendor}" -a -n "${idProduct}" ]; then
				break;
			fi
			idVendor=""
			idProduct=""
		done
	fi

	case "${idProduct}" in
	0x2803)
		firmware=${firmware_dir}/ma003101.bin
		;;
	0x2804)
		firmware=${firmware_dir}/ma004103.bin
		;;
	0x2805)
		firmware=${firmware_dir}/ma005101.bin
		;;
	0x2806)
		firmware=${firmware_dir}/ma006100.bin
		;;
	0x2808)
		firmware=${firmware_dir}/ma008100.bin
		;;
	*)
		err 1 "Unknown product ID"
		;;
	esac

	${command} -R -t 64 -d 0x0763:${idProduct} -D ${firmware} 2>/dev/null 1>&2
	/usr/sbin/usbconfig -d ${dev} reset
}

maudio_init()
{
	local unit dev
	unit=${1#pcm*}
	test -n "${unit}" || return 1
	dev="/dev/mixer${unit}"
	if [ -r ${dev} ]; then
		mixer -f ${dev} vol 100 pcm 100
		if checkyesno maudio_default; then
			sysctl -w hw.snd.default_unit=${unit}
		fi
	fi
}

maudio_attach()
{
	local bus pcmdev pcmdevs

	. ${temp_dir}/state

	case "${1}" in
	pcm*)
		eval "bus=\$maudio_${2}"
		if [ "${bus}" = "1" ]; then
			maudio_init ${1}
		fi
		pcmdevs="${pcmdevs:+${pcmdevs} }${1}"
		echo "pcmdevs=\"${pcmdevs}\"" >${temp_dir}/state
		for pcmdev in ${pcmdevs}; do
			echo "pcmbus_${1}=${2}" >>${temp_dir}/state
		done
		grep "^maudio_" >>${temp_dir}/state
		;;
	uaudio*)
		for pcmdev in ${pcmdevs}; do
			eval "bus=\$pcmbus_${pcmdev}"
			if [ "${bus}" = "${1}" ]; then
				maudio_init ${pcmdev}
				break
			fi
		done
		echo "maudio_${1}=1" >>${temp_dir}/state
		;;
	*)
		err 1 "Unknown device specified"
		;;
	esac
}

maudio_detach()
{
	local pcmdev pcmdevs pcmdevs_new

	. ${temp_dir}/state

	case "${1}" in
	pcm*)
		for pcmdev in ${pcmdevs}; do
			if [ "${pcmdev}" = "${1}" ]; then
				continue
			fi
			pcmdevs_new="${pcmdevs_new:+${pcmdevs_new} }${1}"
		done
		pcmdevs="${pcmdevs_new}"
		sed -i "" -e "/^pcmdevs=/ s/=.*$/=\"${pcmdevs}\"/" -e "/^pcmbus_${1}=/ d" ${temp_dir}/state
		;;
	uaudio*)
		sed -i "" "/^maudio_${1}=/ d" ${temp_dir}/state
		;;
	*)
		err 1 "Unknown device specified"
		;;
	esac
}

run_rc_command $*
