MultiLIRC

From MythTV Official Wiki
Jump to: navigation, search

WORK IN PROGRESS

Multiple LIRC remotes on the same system

Recent versions of lirc allow the use of multiple remotes on the same system. All you need to do is to keep the config files and device names straight.

For example:

/usr/local/sbin/lircd --pidfile=/var/run/lirc_myth.pid --output=/dev/myth/lirc --driver=devinput --device=/dev/myth/remote /etc/lirc/lircd.d/myth.conf

I've hacked up the standard debian lirc init script to automagically start multiple remotes.

First of all, go into /etc/lirc

yan@selene:~$ ls /etc/lirc
hardware.conf	 lircd.conf      lirc-modules-source.conf		lircrc
lircd.conf.dpkg  lircmd.conf  lirc-modules-source.conf.ucf-old

Now create two directories, hardware.d and lircd.d and move hardware.conf and lircd.conf into them:

yan@selene:~$ ls /etc/lirc
hardware.d	 lircd.d      lirc-modules-source.conf		lircrc
lircd.conf.dpkg  lircmd.conf  lirc-modules-source.conf.ucf-old
yan@selene:/etc/lirc$ ls /etc/lirc/hardware.d/
kitchen.conf  myth.conf
yan@selene:/etc/lirc$ ls /etc/lirc/lircd.d/
kitchen.conf  myth.conf

As you can see I have two separate remotes with myth running on separate heads.

# /etc/lirc/hardware.d/myth.conf
#
# Arguments which will be used when launching lircd
# lircd --driver=devinput --device=/dev/myth/remote --output=/dev/myth/lirc \
#    --pidfile=/var/run/lirc_myth.pid 

LIRCD_ARGS=""

START_LIRCD=true

#Don't start lircmd even if there seems to be a good config file
START_LIRCMD=false

#Don't start irexec, even if a good config file seems to exist.
START_IREXEC=false

#Try to load appropriate kernel modules
LOAD_MODULES=true

# Run "lircd --driver=help" for a list of supported drivers.
DRIVER="devinput"
# If DEVICE is set to /dev/lirc and udev is in use /dev/lirc0 will be
# automatically used instead
DEVICE="/dev/myth/remote"
MODULES=""

# Default configuration files for your hardware if any
LIRCD_CONF="/etc/lirc/lircd.d/myth.conf"
LIRCMD_CONF=""

OUTPUT="/dev/myth/lirc"
PIDFILE="/var/run/lirc_myth.pid"

You will need to patch lirc source to get the lirc client lib to get the device name from the environment:

--- lirc-0.8.4a/tools/lirc_client.c	2008-05-20 11:54:37.000000000 -0700
+++ lirc-0.8.4a-ys/tools/lirc_client.c	2009-02-01 15:59:44.000000000 -0800
@@ -142,7 +142,9 @@
 	}
 	
 	addr.sun_family=AF_UNIX;
-	strcpy(addr.sun_path,LIRCD);
+	if (getenv("LIRCD") == NULL) strcpy(addr.sun_path,LIRCD);
+	/* BUFFER OVERRUN WARNING */
+	else strncpy(addr.sun_path,getenv("LIRCD"),127);
 	lirc_lircd=socket(AF_UNIX,SOCK_STREAM,0);
 	if(lirc_lircd==-1)
 	{

And finally replace the lirc file in init.d:

#! /bin/sh
### BEGIN INIT INFO
# Provides:          lirc
# Required-Start:    $remote_fs $syslog
# Required-Stop:     $remote_fs $syslog
# Default-Start:     2 3 4 5
# Default-Stop:      0 1 6
# Short-Description: Starts LIRC daemon.
# Description:       LIRC is used to control different
#                    infrared receivers and transceivers.
### END INIT INFO

LIRCD=/usr/local/sbin/lircd
LIRCMD=/usr/local/sbin/lircmd
IREXEC=/usr/local/sbin/irexec

load_modules ()
{
	MODULES_MISSING=false

	for mod in $*
	do
		modprobe $mod 2> /dev/null || MODULES_MISSING=true
	done

	if [ "$MODULES_MISSING" = true ]; then
		echo "#####################################################"
		echo "## I couldn't load the required kernel modules     ##"
		echo "## You should install lirc-modules-source to build ##"
		echo "## kernel support for your hardware.               ##"
		echo "#####################################################"
		echo "## If this message is not appropriate you may set  ##"
		echo "## LOAD_MODULES=false in /etc/lirc/hardware.conf   ##"
		echo "#####################################################"
		START_LIRCMD=false
		START_LIRCD=false
	fi

	unset -v MODULES_MISSING

	# avoid a hard dependency or a flag day between udev versions
	if [ -x /sbin/udevadm ]; then
		# udev >= 0.117
		udevadm settle || echo "timeout waiting for devices to be ready"
	elif [ -x /sbin/udevsettle ]; then
		# udev < 0.117
		udevsettle || echo "timeout waiting for devices to be ready"
	fi
}

build_args ()
{
	ARGS="$*"

	## Try to find an lirc device.
	## udev uses /dev/lirc0
	## static dev uses /dev/lirc
	if [ -z "$DEVICE" ]; then
		for dev in /dev/lirc0 /dev/lirc; do
			if [ -c $dev ]; then
				DEVICE="$dev"
				break
			fi
		done
	fi
	
	if [ -n "$DEVICE" ] && [ "$DEVICE" != "none" ]; then
		ARGS="--device=$DEVICE $ARGS"
	fi
	if [ -n "$DRIVER" ] && [ "$DRIVER" != "none" ]; then
		ARGS="--driver=$DRIVER $ARGS"
	fi
        if [ -n "$OUTPUT" ] && [ "$OUTPUT" != "none" ]; then
                ARGS="--output=$OUTPUT $ARGS"
        fi
        if [ -n "$PIDFILE" ] && [ "$PIDFILE" != "none" ]; then
                ARGS="--pidfile=$PIDFILE $ARGS"
        fi
        if [ -n "$LIRCD_CONF" ] && [ "$LIRCD_CONF" != "none" ]; then
                ARGS="$ARGS $LIRCD_CONF"
        fi
	echo $ARGS

	unset -v ARGS
}

test -f $LIRCD || exit 0
#test -f /usr/sbin/lircmd || exit 0
#test -f /etc/lirc/lircd.conf || exit 0
#test -f /etc/lirc/lircmd.conf || exit 0

START_LIRCMD=true
START_LIRCD=true
START_IREXEC=true

check_config()
{
	if [ -f /etc/lirc/UNCONFIGURED ]; then
		echo "##################################################"
		echo "## LIRC IS NOT CONFIGURED                       ##"
		echo "##                                              ##"
		echo "## read /usr/share/doc/lirc/html/configure.html ##"
		echo "##################################################"
		START_LIRCD=false
		START_LIRCMD=false
		START_IREXEC=false
		fi
}

start()
{
    if [ "$LOAD_MODULES" = "true" ] && [ "$START_LIRCD" = "true" ]; then
	load_modules $MODULES
    fi
    echo -n "Starting lirc daemon:"
    if [ "$START_LIRCD" = "true" ]; then
      echo -n " lircd"
      LIRCD_ARGS=`build_args $LIRCD_ARGS`
      start-stop-daemon --start --quiet --exec $LIRCD -- $LIRCD_ARGS \
		< /dev/null
    fi
    if [ "$START_LIRCMD" = "true" ]; then
      echo -n " lircmd"
      start-stop-daemon --start --quiet --exec $LIRCMD \
      		< /dev/null
    fi
    if [ "$START_IREXEC" = "true" ]; then
      echo -n " irexec"
      start-stop-daemon --start --quiet --exec $IREXEC -- -d /etc/lirc/lircrc \
      		< /dev/null
    fi
    echo "."
}

clean()
{
unset LIRCD_ARGS
unset START_LIRCMD
unset START_IREXEC
unset LOAD_MODULES
unset DRIVER
unset DEVICE
unset MODULES
unset LIRCD_CONF
unset LIRCMD_CONF
}

case "$1" in
  start)
	for hconf in /etc/lirc/hardware.d/*.conf ; do
		echo starting $hconf
		. $hconf
		check_config
		build_args
		start
		clean
		done
    echo "."
    ;;
  stop)
    echo -n "Stopping lirc daemon:"
    echo -n " irexec"
    start-stop-daemon --stop --quiet --exec $IREXEC
    echo -n " lircmd"
    start-stop-daemon --stop --quiet --exec $LIRCD
    echo -n " lircd"
    start-stop-daemon --stop --quiet --exec $LIRCMD
    echo "."
    ;;
  reload|force-reload)
    if [ "$START_IREXEC" = "true" ]; then
      start-stop-daemon --stop --quiet --signal 1 --exec $IREXEC
    fi
    if [ "$START_LIRCD" = "true" ]; then
      start-stop-daemon --stop --quiet --signal 1 --exec $LIRCD
    fi
    if [ "$START_LIRCMD" = "true" ]; then
      start-stop-daemon --stop --quiet --signal 1 --exec $LIRCMD
    fi
    ;;
  restart)
    $0 stop
    $0 start
    ;;
  *)
    echo "Usage: /etc/init.d/lircd {start|stop|reload|restart|force-reload}"
    exit 1
esac

exit 0

Now to use it all, just add the name of the lirc device to the environemnt. This name has to match the OUTPUT var in the hardware.d/XXX.conf file; so for the example above you could use

LIRCD=/dev/myth/lirc mythfrontend

and that's all there is to it....