diff -r b3d9ca0b0e6f -r 96e25bd5d144 linux/drivers/media/video/v4l2_extension/v4l2_extension-hlp.c
--- a/linux/drivers/media/video/v4l2_extension/v4l2_extension-hlp.c	Fri Aug 10 21:47:50 2007 +0200
+++ b/linux/drivers/media/video/v4l2_extension/v4l2_extension-hlp.c	Wed Oct 03 21:17:26 2007 +0200
@@ -23,6 +23,119 @@
 
 #include "v4l2_extension.h"
 
+#define HELPER_IF_NAME              "v4l2_extension"
+
+/* helper_daemon states if the helper daemon has opened the driver */
+static int helper_daemon=0;
+static struct mutex helper_daemon_lock;
+
+/* device management stuff */
+static struct class *helper_class;
+static int helper_major;
+
+/* ----------------------------------------------------------- */
+/*
+ * Helper daemon interface operations
+ */
+
+
+int v4l2ext_hlp_ioctl(struct inode *inode, struct file *file,
+		      unsigned int cmd, unsigned long arg) {
+	return 0;
+}
+
+/* map shared memory between the helper daemon and this driver
+   in order to transmit uncompressed frames */
+static int v4l2ext_hlp_mmap(struct file *file, struct vm_area_struct *vma)
+{
+	return 0;
+}
+
+static unsigned int v4l2ext_hlp_poll(struct file *file, poll_table *wait)
+{
+	struct helperd *dev = file->private_data;
+	poll_wait(file, &dev->waitqueue, wait);
+	return POLLIN | POLLRDNORM;
+}
+
+static int v4l2ext_hlp_open(struct inode *inode, struct file *file) {
+	struct helperd *dev = NULL;
+
+	if(helper_daemon==1) {
+		return -EBUSY;
+	}
+	else {
+		mutex_lock(&helper_daemon_lock);
+		/* Helper daemon is here */
+		helper_daemon = 1;
+		mutex_unlock(&helper_daemon_lock);
+	}
+	/* allocate and initialize device private data structure */
+	dev = kzalloc(sizeof(*dev),GFP_KERNEL);
+	if (NULL == dev) {
+		printk("cannot allocate device.\n");
+		return -ENOMEM;
+	}
+
+	init_waitqueue_head(&dev->waitqueue);
+	file->private_data = dev;
+	return 0;
+
+	return 0;
+}
+
+static int v4l2ext_hlp_release(struct inode *inode, struct file *file) {
+
+	mutex_lock(&helper_daemon_lock);
+	/* Helper daemon has gone */
+	helper_daemon = 0;
+	kfree(file->private_data);
+
+	mutex_unlock(&helper_daemon_lock);
+
+	return 0;
+}
+
+static const struct file_operations v4l2ext_hlp_fops=
+{
+	.owner		= THIS_MODULE,
+	.llseek		= no_llseek,
+	.open		= v4l2ext_hlp_open,
+	.poll		= v4l2ext_hlp_poll,
+	.release	= v4l2ext_hlp_release,
+	.mmap		= v4l2ext_hlp_mmap,
+	.ioctl		= v4l2ext_hlp_ioctl
+};
+
+int v4l2ext_hlp_init(void) {
+
+	/* Unnamed device creation */
+	helper_major = register_chrdev(0, HELPER_IF_NAME, &v4l2ext_hlp_fops);
+	if(helper_major<0) {
+		printk(KERN_WARNING "v4l2_extension: unable to get major 0\n");
+		return -EIO;
+	}
+
+	/* create a driver class in order to automate udev */
+	helper_class = class_create(THIS_MODULE, HELPER_IF_NAME);
+	if (!helper_class)
+		return -EINVAL;
+
+	class_device_create(helper_class,
+			    NULL,
+			    MKDEV(helper_major, 0),
+			    NULL, HELPER_IF_NAME);
+
+	mutex_init(&helper_daemon_lock);
+
+	return 0;
+}
+
+void v4l2ext_hlp_fini(void) {
+	class_device_destroy(helper_class, MKDEV(helper_major, 0));
+	unregister_chrdev(0, HELPER_IF_NAME);
+	class_destroy(helper_class);
+}
 /* ----------------------------------------------------------- */
 /*
  * Local variables:
diff -r b3d9ca0b0e6f -r 96e25bd5d144 linux/drivers/media/video/v4l2_extension/v4l2_extension-video.c
--- a/linux/drivers/media/video/v4l2_extension/v4l2_extension-video.c	Fri Aug 10 21:47:50 2007 +0200
+++ b/linux/drivers/media/video/v4l2_extension/v4l2_extension-video.c	Wed Oct 03 21:17:26 2007 +0200
@@ -537,6 +537,9 @@ static int v4l2ext_init(void)
 	       (V4L2EXT_VERSION_CODE >>  8) & 0xff,
 	       V4L2EXT_VERSION_CODE & 0xff);
 
+	/* activate the v4l2 helper daemon interface */
+	v4l2ext_hlp_init();
+
 	return 0;
 }
 
@@ -544,6 +547,10 @@ static void v4l2ext_fini(void)
 {
 	struct v4l2ext *h;
 	struct list_head *list;
+
+	/* remove the v4l2 helper daemon interface */
+	v4l2ext_hlp_fini();
+
 	/* remove any registered base v4l structure */
 	list_for_each(list,&v4l2ext_devlist) {
 		h = list_entry(list, struct v4l2ext, devlist);
diff -r b3d9ca0b0e6f -r 96e25bd5d144 linux/drivers/media/video/v4l2_extension/v4l2_extension.h
--- a/linux/drivers/media/video/v4l2_extension/v4l2_extension.h	Fri Aug 10 21:47:50 2007 +0200
+++ b/linux/drivers/media/video/v4l2_extension/v4l2_extension.h	Wed Oct 03 21:17:26 2007 +0200
@@ -48,6 +48,19 @@ void v4l2ext_unregister(struct video_dev
 
 
 /***************************************************************************/
+/* v4l2 helper daemon interface                                            */
+/***************************************************************************/
+int v4l2ext_hlp_init(void);
+void v4l2ext_hlp_fini(void);
+
+/***************************************************************************/
+/* v4l2 helper daemon private interface                                    */
+/***************************************************************************/
+struct helperd {
+	wait_queue_head_t waitqueue;
+};
+
+/***************************************************************************/
 /* v4l2 extension driver private interface                                 */
 /***************************************************************************/
 
diff -r b3d9ca0b0e6f -r 96e25bd5d144 v4l2-apps/Makefile
--- a/v4l2-apps/Makefile	Fri Aug 10 21:47:50 2007 +0200
+++ b/v4l2-apps/Makefile	Wed Oct 03 21:17:26 2007 +0200
@@ -6,6 +6,7 @@ all clean install:
 	$(MAKE) -C lib $@
 	$(MAKE) -C util $@
 	$(MAKE) -C test $@
+	$(MAKE) -C v4l2ext_helper $@
 
 %:
 	make -C .. $(MAKECMDGOALS)
diff -r b3d9ca0b0e6f -r 96e25bd5d144 v4l2-apps/v4l2ext_helper/99-v4l2ext.rules
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/v4l2-apps/v4l2ext_helper/99-v4l2ext.rules	Wed Oct 03 21:17:26 2007 +0200
@@ -0,0 +1,1 @@
+SUBSYSTEM=="v4l2_extension", ACTION=="add", RUN+="/usr/sbin/v4l2ext_helper"
diff -r b3d9ca0b0e6f -r 96e25bd5d144 v4l2-apps/v4l2ext_helper/Makefile
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/v4l2-apps/v4l2ext_helper/Makefile	Wed Oct 03 21:17:26 2007 +0200
@@ -0,0 +1,32 @@
+# Makefile for linuxtv.org v4l2-apps/test
+BINPATH=$(DESTDIR)/usr/sbin
+
+INSTALL = /bin/ginstall -c
+INSTALL_PROGRAM = ${INSTALL}
+INSTALL_DATA = ${INSTALL} -m 644
+
+CPPFLAGS += -I../../linux/include
+
+binaries = v4l2ext_helper
+
+.PHONY: all clean install
+
+all: $(binaries)
+
+clean::
+	rm -f $(binaries)
+
+install:
+	$(INSTALL_DATA) 99-v4l2ext.rules /etc/udev/rules.d/
+	/sbin/udevcontrol reload_rules
+	$(INSTALL_PROGRAM) $(binaries) $(BINPATH)
+
+../lib/libv4l2.a: ../lib/v4l2_driver.c ../lib/frequencies.c
+	make -C ../lib libv4l2.a
+
+v4l2ext_helper: v4l2ext_helper.o ../lib/libv4l2.a
+
+#pixfmt-test: pixfmt-test.o
+#	$(CC) $(LDFLAGS) $^ $(LOADLIBES) $(LDLIBS) -o $@ -lX11
+
+include ../Make.rules
diff -r b3d9ca0b0e6f -r 96e25bd5d144 v4l2-apps/v4l2ext_helper/v4l2ext_helper.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/v4l2-apps/v4l2ext_helper/v4l2ext_helper.c	Wed Oct 03 21:17:26 2007 +0200
@@ -0,0 +1,241 @@
+/*
+  v4l2 helper daemon
+  * (c) Thierry Merle <thierry.merle@free.fr>
+  *
+  *  Taken from Unix Daemon Server Programming example here:
+  *  http://www.enderunix.org/docs/eng/daemon.php
+  *  and Doug Potter's howto daemonize here:
+  *  http://www-theorie.physik.unizh.ch/~dpotter/howto/daemonize
+  *
+  *  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., 675 Mass Ave, Cambridge, MA 02139, USA.
+  */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <syslog.h>
+#include <errno.h>
+#include <pwd.h>
+#include <signal.h>
+
+#define DAEMON_NAME	"v4l2ext_helperd"
+#define RUN_AS_USER "root"
+#define V4L2EXT_DEVICE "/dev/v4l2_extension"
+
+#define EXIT_SUCCESS 0
+#define EXIT_FAILURE 1
+
+/* As default, start as daemon */
+static int as_daemon=1;
+
+#define LOG(level,fmt,args...) \
+	{ if(as_daemon) syslog(level,fmt,##args); \
+	else printf(fmt,##args); }
+
+
+void usage(void) {
+	extern char *__progname;
+
+
+	fprintf(stderr, "usage: %s [-s] [-h] \n"
+		"V4L2 helper daemon.\n"
+		"arguments:\n"
+		"-s: start as standalone program (instead of a daemon)\n"
+		"-h: display this help message.\n",
+		__progname);
+	exit(EXIT_FAILURE);
+}
+
+static void child_handler(int signum)
+{
+    switch(signum) {
+    case SIGALRM: exit(EXIT_FAILURE); break;
+    case SIGUSR1: exit(EXIT_SUCCESS); break;
+    case SIGCHLD: exit(EXIT_FAILURE); break;
+    }
+}
+
+static int daemonize( const char *lockfile )
+{
+    pid_t pid, sid, parent;
+    int lfp = -1;
+
+    /* already a daemon */
+    if ( getppid() == 1 ) return 0;
+
+    /* Create the lock file as the current user */
+    if ( lockfile && lockfile[0] ) {
+	lfp = open(lockfile,O_RDWR|O_CREAT,0640);
+	if ( lfp < 0 ) {
+		LOG( LOG_ERR, "unable to create lock file %s, code=%d (%s)",
+		     lockfile, errno, strerror(errno) );
+		return EXIT_FAILURE;
+	}
+    }
+
+    /* Drop user if there is one, and we were run as root */
+    if ( getuid() == 0 || geteuid() == 0 ) {
+	struct passwd *pw = getpwnam(RUN_AS_USER);
+	if ( pw ) {
+	    LOG( LOG_NOTICE, "setting user to " RUN_AS_USER );
+	    setuid( pw->pw_uid );
+	}
+    }
+
+    /* Trap signals that we expect to recieve */
+    signal(SIGCHLD,child_handler);
+    signal(SIGUSR1,child_handler);
+    signal(SIGALRM,child_handler);
+
+    /* Fork off the parent process */
+    pid = fork();
+    if (pid < 0) {
+	LOG( LOG_ERR, "unable to fork daemon, code=%d (%s)",
+		errno, strerror(errno) );
+	return EXIT_FAILURE;
+    }
+    /* If we got a good PID, then we can exit the parent process. */
+    if (pid > 0) {
+
+	/* Wait for confirmation from the child via SIGTERM or SIGCHLD, or
+	   for two seconds to elapse (SIGALRM).  pause() should not return. */
+	alarm(2);
+	pause();
+
+	return EXIT_FAILURE;
+    }
+
+    /* At this point we are executing as the child process */
+    parent = getppid();
+
+    /* Cancel certain signals */
+    signal(SIGCHLD,SIG_DFL); /* A child process dies */
+    signal(SIGTSTP,SIG_IGN); /* Various TTY signals */
+    signal(SIGTTOU,SIG_IGN);
+    signal(SIGTTIN,SIG_IGN);
+    signal(SIGHUP, SIG_IGN); /* Ignore hangup signal */
+    signal(SIGTERM,SIG_DFL); /* Die on SIGTERM */
+
+    /* Change the file mode mask */
+    umask(0);
+
+    /* Create a new SID for the child process */
+    sid = setsid();
+    if (sid < 0) {
+	LOG( LOG_ERR, "unable to create a new session, code %d (%s)",
+		errno, strerror(errno) );
+	return EXIT_FAILURE;
+    }
+
+    /* Change the current working directory.  This prevents the current
+       directory from being locked; hence not being able to remove it. */
+    if ((chdir("/")) < 0) {
+	LOG( LOG_ERR, "unable to change directory to %s, code %d (%s)",
+		"/", errno, strerror(errno) );
+	return EXIT_FAILURE;
+    }
+
+    /* Redirect standard files to /dev/null */
+    freopen( "/dev/null", "r", stdin);
+    freopen( "/dev/null", "w", stdout);
+    freopen( "/dev/null", "w", stderr);
+
+    /* Tell the parent process that we are A-okay */
+    kill( parent, SIGUSR1 );
+
+    return 0;
+}
+
+int main( int argc, char *argv[] ) {
+
+    int ch;
+    int fd;
+    fd_set fds;
+    int r;
+    char buffer[512];
+
+    /* Initialize the logging interface */
+    openlog( DAEMON_NAME, LOG_PID, LOG_LOCAL5 );
+    LOG( LOG_INFO, "starting" );
+
+    /* Process command-line arguments */
+    while ((ch = getopt(argc, argv, "sh")) != -1) {
+	    switch (ch) {
+	    case 's':
+		    as_daemon=0;
+		    break;
+	    case 'h':
+		    usage();
+		    break;
+	    default:
+		    usage();
+	    }
+    }
+
+    argc -= optind;
+    argv += optind;
+
+    /* Daemonize */
+    if(as_daemon) {
+	    if((r = daemonize( "/var/lock/subsys/" DAEMON_NAME )) !=
+	       EXIT_SUCCESS) {
+		    perror("Failed to daemonize");
+		    return r;
+	    }
+    }
+    else {
+	    printf("Starting as standalone process\n");
+    }
+
+    /* open the helper daemon entry point
+       to communicate with the v4l2_extension driver */
+    fd = open(V4L2EXT_DEVICE,O_RDWR);
+    if (fd < 0) {
+	    perror("failed to open v4l2 extension entry point "V4L2EXT_DEVICE);
+	    return EXIT_FAILURE;
+    }
+
+    for(;;) {
+	    FD_ZERO(&fds);
+	    FD_SET(fd, &fds);
+	    if (select(fd + 1, &fds, NULL, NULL, 0) <= 0) {
+		    continue;
+	    }
+
+	    /* react to the devices's request */
+	    r = read(fd, buffer, sizeof(buffer));
+	    if (r <= 0) {
+		    LOG( LOG_ERR, "error on read (%s)",strerror(errno));
+		    return EXIT_FAILURE;
+	    }
+    }
+
+    /* Finish up */
+    LOG( LOG_NOTICE, "terminated" );
+    closelog();
+    return EXIT_FAILURE;
+}
+
+/* ----------------------------------------------------------- */
+/*
+ * Local variables:
+ * c-basic-offset: 8
+ * End:
+ * kate: eol "unix"; indent-width 3; remove-trailing-space on; replace-trailing-space-save on; tab-width 8; replace-tabs off; space-indent off; mixed-indent off
+ */
