Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 10 Oct 2008 17:41:34 +0000 (UTC)
From:      Rui Paulo <rpaulo@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-user@freebsd.org
Subject:   svn commit: r183746 - user/rpaulo/aird
Message-ID:  <200810101741.m9AHfYgJ096932@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: rpaulo
Date: Fri Oct 10 17:41:34 2008
New Revision: 183746
URL: http://svn.freebsd.org/changeset/base/183746

Log:
  Apple IR daemon. Makes the Apple remote functional under FreeBSD.
  Imported from P4.

Added:
  user/rpaulo/aird/
  user/rpaulo/aird/Makefile   (contents, props changed)
  user/rpaulo/aird/aird.1   (contents, props changed)
  user/rpaulo/aird/aird.c   (contents, props changed)

Added: user/rpaulo/aird/Makefile
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ user/rpaulo/aird/Makefile	Fri Oct 10 17:41:34 2008	(r183746)
@@ -0,0 +1,10 @@
+# $P4: //depot/user/rpaulo/aird/Makefile#1 $
+
+PROG=	aird
+MAN=	aird.1
+WARNS?=	6
+
+DPADD=	${LIBUTIL}
+LDADD=	-lutil
+
+.include <bsd.prog.mk>

Added: user/rpaulo/aird/aird.1
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ user/rpaulo/aird/aird.1	Fri Oct 10 17:41:34 2008	(r183746)
@@ -0,0 +1,180 @@
+.\"
+.\" Copyright (c) 2007 Rui Paulo <rpaulo@FreeBSD.org>
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+.\" IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+.\" WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+.\" DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
+.\" INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+.\" (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+.\" SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+.\" STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+.\" ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+.\" POSSIBILITY OF SUCH DAMAGE.
+.\"
+.\" $P4: //depot/user/rpaulo/aird/aird.1#1 $
+.\"
+.Dd July 30, 2007
+.Dt AIRD 1
+.Sh NAME
+.Nm aird
+.Nd "USB Apple IR receiver daemon"
+.Sh SYNOPSIS
+.Nm
+.Op Fl vd
+.Op Fl p Ar pidfile
+.Op Fl k Ar key
+.Fl f Ar device
+.Op Fl M Ar menu command
+.Op Fl P Ar play command
+.Op Fl F Ar forward command
+.Op Fl B Ar backward command
+.Op Fl U Ar volume up command
+.Op Fl D Ar volume down command
+.Sh DESCRIPTION
+The
+.Nm
+daemon handles Apple IR receiver button events.
+If your system has an USB Apple IR receiver, most likely you'll also
+have an Apple Remote.
+An Apple remote has six (6) buttons: Volume up, Volume down,
+Play/Pause, Forward, Backward and Menu.
+For each button you can assign a command to execute.
+.Pp
+Apple IR receiver modules are found on:
+.Pp
+.Bl -bullet -offset indent -compact
+.It
+MacBook (any generation)
+.It
+MacBook Pro (any generation)
+.It
+Intel iMac
+.It
+Intel MacMini
+.El
+.Pp
+The following program options are available:
+.Bl -tag -width indent
+.It Fl v
+Enable verbose mode.
+.It Fl d
+Toggles the daemon flag.
+.It Fl p Ar pidfile
+Use the specified file to store the process ID.
+.It Fl f Ar device
+Read from the specified device entry. This is mandatory.
+.It Fl k Ar key
+Only accept commands from the remote with the specified
+.Pa key .
+See the
+.Sx EXAMPLES
+section to understand how remote pairing works.
+.El
+.Pp
+The following options specify commands to run upon button down
+events:
+.Bl -tag -width indent
+.It Fl M Ar menu command
+Command to run when the daemon recieves a notification that the
+.Em Menu
+button was pressed.
+.It Fl P Ar play command
+Command to run when the daemon recieves a notification that the
+.Em Play/Pause
+button was pressed.
+.It Fl F Ar forward command
+Command to run when the daemon recieves a notification that the
+.Em Forward
+button was pressed.
+.It Fl B Ar backward command
+Command to run when the daemon recieves a notification that the 
+.Em Backward
+button was pressed.
+.It Fl U Ar volume up command
+Command to run when the daemon recieves a notification that the
+.Em Volume Up
+button was pressed.
+.It Fl D Ar volume down command
+Command to run when the daemon recieves a notification that the
+.Em Volume Down
+button was pressed.
+.El
+.Pp
+Note that lower case options are program options and upper case
+options specify the commands to run upon button down events.
+.Sh FILES
+.Bl -tag -width indent
+.It Pa /var/run/aird.pid
+The default location of the PID file.
+.El
+.Sh EXAMPLES
+To pair a remote controller with your IR receiver, do the following:
+.Bd -literal -offset indent
+aird -f /dev/uhid1 -k 0
+.Ed
+.Pp
+Then press the
+.Pa Menu
+and
+.Pa Forward
+keys at the same time for five seconds. The following will show up:
+.Bd -literal -offset indent
+Your Apple remote pairing key is: 131
+Next time you run aird, pass this number as the -k argument.
+.Ed
+.Pp
+This example shows how to control
+.Xr mpd 1
+with
+.Xr aird 1 .
+You need
+.Xr mpc 1
+and
+.Xr ncmpc 1
+installed.
+Run
+.Xr aird 1
+from your
+.Pa ~/.xinitrc
+startup file like this:
+.Bd -literal -offset indent
+aird -p ~/.aird.pid -f /dev/uhid1 -P "mpc toggle" -F "mpc next" \\
+  -B "mpc prev" -U "mixer vol +2" -D "mixer vol -2"  \\
+  -M "xterm -e ncmpc"
+.Ed
+.Pp
+If you want to stop other users from gaining control of the IR receiver
+and to prevent commands to be executed when someone presses a button
+on the remote control, run
+.Xr aird 1
+only with the
+.Fl f
+argument:
+.Bd -literal -offset indent
+aird -f /dev/uhid1
+.Ed
+.Sh SEE ALSO
+.Xr mpd 1 Pq Pa ports/audio/musicpd ,
+.Xr mpc 1 Pq Pa ports/audio/mpc ,
+.Xr ncmpc 1 Pq Pa ports/audio/ncmpc ,
+.Xr uhid 4 ,
+.Xr usb 4
+.Sh HISTORY
+The
+.Nm
+utility first appeared in
+.Fx 8.0 .
+.Sh AUTHORS
+.An Rui Paulo Aq rpaulo@FreeBSD.org

Added: user/rpaulo/aird/aird.c
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ user/rpaulo/aird/aird.c	Fri Oct 10 17:41:34 2008	(r183746)
@@ -0,0 +1,317 @@
+/*-
+ * Copyright (c) 2007 Rui Paulo <rpaulo@FreeBSD.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $P4: //depot/user/rpaulo/aird/aird.c#1 $
+ *
+ */
+
+/*
+ * aird - a deamon to interact with an USB Apple IR receiver.
+ *        Runs commands for each key pressed.
+ *
+ * This daemon reads an uhid(4) device 6 bytes each time.
+ * For example, when the user presses the volume up, the read buffer will
+ * contain:
+ *  0x25 0x87 0xee 0x[any] 0x0a/0x0b
+ * 0x[any] means that there can be any value in that byte (as it's remote
+ * controller dependent). The last byte is also hardware dependent.
+ *
+ * When I key is repeated the read will return:
+ *  0x26 0x00 0x00 0x00 0x00
+ *
+ * For flat batteries we only check the value of the third byte (0xe0) and
+ * send a syslog warning.
+ *
+ * All the magic numbers came from the Linux appleir driver (now integrated
+ * into LIRC).
+ *
+ */
+
+#if 0
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+#endif
+
+#include <err.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <signal.h>
+#include <syslog.h>
+#include <unistd.h>
+
+#include <inttypes.h>
+
+#include <sys/param.h>
+#include <sys/ioctl.h>
+#include <sys/stat.h>
+
+#include <libutil.h>
+#include <dev/usb/usb.h>
+#include <dev/usb/usbhid.h>
+
+static struct pidfh *pfh;
+
+static void	sighandler(int sig);
+static void 	usage(void);
+static void 	runcmd(const char *cmd, int fd);
+
+
+static void
+sighandler(__unused int sig)
+{
+
+	if (pfh)
+		pidfile_remove(pfh);
+
+	exit(EXIT_SUCCESS);
+}
+
+static void
+usage(void)
+{
+	fprintf(stderr, "usage: %s [-vd] [-p pidfile] -f device "
+	    "[-M menu command]\n\t[-P play command] [-F forward command] "
+	    "[-B backward command]\n\t[-U volume up command] "
+	    "[-D volume down command]\n", getprogname());
+
+	exit(1);
+}
+
+static void
+runcmd(const char *cmd, int fd)
+{
+	int r;
+
+	if (fork() == 0) {
+		close(fd);
+		signal(SIGCHLD, SIG_DFL);
+		r = system(cmd);
+		_exit(r);
+	}
+}
+
+int
+main(int argc, char *argv[])
+{
+	int fd;
+	int inpair;
+	int repeating;
+	char ch;
+	unsigned char buf[5];
+	unsigned char prevbuf[5];
+	int foreground;
+	int verbose;
+	char *cmd_menu, *cmd_play, *cmd_forward, *cmd_backward,
+	    *cmd_volup, *cmd_voldown;
+	pid_t otherpid;
+	const char *pidfile;
+	const char *deventry;
+	unsigned char key;
+
+	pfh = NULL;
+
+	signal(SIGHUP, sighandler);
+	signal(SIGINT, sighandler);
+	signal(SIGCHLD, SIG_IGN);
+
+	deventry     = NULL;
+	foreground   = 0;
+	verbose	     = 0;
+	repeating    = 0;
+	cmd_menu     = NULL;
+	cmd_play     = NULL;
+	cmd_forward  = NULL;
+	cmd_backward = NULL;
+	cmd_volup    = NULL;
+	cmd_voldown  = NULL;
+	pidfile      = "/var/run/aird.pid";
+	key	     = 0;
+	inpair	     = 0;
+	
+	while ((ch = getopt(argc, argv, "f:dvk:p:M:P:F:B:U:D:?")) != -1)
+		switch (ch) {
+		case 'f':
+			deventry = optarg;
+			break;
+		case 'd':
+			foreground = 1;
+			break;
+		case 'v':
+			verbose = 1;
+			break;
+		case 'k':
+			key = atoi(optarg);
+			if (key == 0) {
+				foreground = 1;
+				inpair = 1;
+			}
+			break;
+		case 'M':
+			cmd_menu = optarg;
+			break;
+		case 'P':
+			cmd_play = optarg;
+			break;
+		case 'F':
+			cmd_forward = optarg;
+			break;
+		case 'B':
+			cmd_backward = optarg;
+			break;
+		case 'U':
+			cmd_volup = optarg;
+			break;
+		case 'D':
+			cmd_voldown = optarg;
+			break;
+		case 'p':
+			pidfile = optarg;
+			break;
+		case '?':
+		default:
+			usage();
+			/* NOTREACHED */
+		}
+        argc -= optind;
+        argv += optind;
+
+	if (!deventry)
+		usage();
+
+	fd = open(deventry, O_RDONLY);
+	if (fd < 0)
+		err(EXIT_FAILURE, "open %s", deventry);
+
+	if (!foreground) {
+		pfh = pidfile_open(pidfile, 0600, &otherpid);
+		if (pfh == NULL) {
+			if (errno == EEXIST) {
+				errx(EXIT_FAILURE,
+				    "Daemon already running, pid: %jd.",
+				    (intmax_t)otherpid);
+			}
+			/* If we cannot create pidfile from other reasons,
+			   only warn. */
+			warn("Cannot open or create pidfile");
+		}
+		
+		if (daemon(0, 0) < 0) {
+			pidfile_remove(pfh);
+			err(EXIT_FAILURE, "daemon");
+		}
+		pidfile_write(pfh);
+	}
+	
+	memset(prevbuf, 0, sizeof(prevbuf));
+	while (read(fd, &buf, sizeof(buf)) >= 0) {
+		if (verbose)
+			fprintf(stderr, "%x %x %x %x %x\n", buf[0], buf[1],
+			    buf[2], buf[3], buf[4]);
+
+		/*
+		 * Handle pairing.
+		 */
+		if (inpair && buf[2] == 0xe0) {
+			fprintf(stderr, "Your Apple remote pairing key is: "
+			    "%d\n"
+			    "Next time you run aird, pass this number as the "
+			    "-k argument.\n", buf[3]);
+			exit(EXIT_SUCCESS);
+		}
+
+		if (key && buf[3] != key)
+			continue;
+		
+		/*
+		 * Check for key repeats.
+		 */
+		if (buf[0] == 0x26)
+			repeating++;
+		else {
+			memcpy(prevbuf, buf, sizeof(prevbuf));
+			repeating = 0;
+		}
+
+		/*
+		 * The controller can generate repeating key codes
+		 * very fast and this makes a lot of users upset.
+		 *
+		 * This check makes the program only consider repeats
+		 * if the key has been pressed for actually 1 second.
+		 */
+		if (repeating >= 5) {
+			if (verbose)
+				fprintf(stderr, "repeating key: %x %x %x %x "
+				    "%x\n", prevbuf[0], prevbuf[1],
+				    prevbuf[2], prevbuf[3], prevbuf[4]);
+			
+			memcpy(buf, prevbuf, sizeof(buf));
+			repeating = 0;
+		}
+		
+		switch (buf[4]) {
+		/* Menu */	
+		case 0x02:
+		case 0x03:
+			runcmd(cmd_menu, fd);
+			break;
+		/* Play/Pause */
+		case 0x04:
+		case 0x05:
+			runcmd(cmd_play, fd);
+			break;
+		/* Forward */
+		case 0x06:
+		case 0x07:
+			runcmd(cmd_forward ,fd);
+			break;
+		/* Backward */
+		case 0x08:
+		case 0x09:
+			runcmd(cmd_backward, fd);
+			break;
+		/* Volume Up */
+		case 0x0a:
+		case 0x0b:
+			runcmd(cmd_volup, fd);
+			break;
+		/* Volume Down */
+		case 0x0c:
+		case 0x0d:
+			runcmd(cmd_voldown, fd);
+			break;
+
+		}
+
+	}
+	pidfile_remove(pfh);
+	close(fd);
+
+	return (0);
+}



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200810101741.m9AHfYgJ096932>