changeset 8:80590d10a596

Added num of buffers as a module param, indent code using spaces instead of tabs
author AngelCarpintero
date Tue, 26 Aug 2008 11:50:37 +0000
parents 2fce9e157b8d
children 00bb25bff577
files Makefile vloopback.c
diffstat 2 files changed, 890 insertions(+), 860 deletions(-) [+]
line wrap: on
line diff
--- a/Makefile	Sun Aug 24 02:20:51 2008 +0000
+++ b/Makefile	Tue Aug 26 11:50:37 2008 +0000
@@ -1,8 +1,9 @@
 VERSION=trunk
+MODULENAME=vloopback
 
 ifneq ($(KERNELRELEASE),)
 
-obj-m	:= vloopback.o
+obj-m	:= $(MODULENAME).o
 
 else
 
@@ -29,12 +30,12 @@
 
 install:
 	install -d $(DEST)
-	install -m 644 -c vloopback.ko $(DEST)
+	install -m 644 -c $(MODULENAME).ko $(DEST)
 	-/sbin/depmod -a
 
 	
 uninstall:
-	rm -f $(DEST)/vloopback.ko
+	rm -f $(DEST)/$(MODULENAME).ko
 	-/sbin/depmod -a
 clean:
 	rm -f .*.cmd *.o *.mod.c *.ko .v* *~ core Modules.symvers Module.symvers
--- a/vloopback.c	Sun Aug 24 02:20:51 2008 +0000
+++ b/vloopback.c	Tue Aug 26 11:50:37 2008 +0000
@@ -1,153 +1,157 @@
 /*
- *	vloopback.c
+ *    vloopback.c
  *
- *	Copyright Jeroen Vreeken (pe1rxq@amsat.org), 2000
- *	Additional copyright by the contributing authors in the
- *	change history below, 2000-2007
+ *    Copyright Jeroen Vreeken (pe1rxq@amsat.org), 2000
+ *    Additional copyright by the contributing authors in the
+ *    change history below, 2000-2007
  *
- *	Published under the GNU Public License.
+ *    Published under the GNU Public License.
  *
- *	The Video loopback Loopback Device is no longer systematically maintained.
- *	The project is a secondary project for the project "motion" found at
- *	http://motion.sourceforge.net/ and
- *	http://www.lavrsen.dk/twiki/bin/view/Motion/WebHome
- *	and with the vloopback stored at
- *	http://www.lavrsen.dk/twiki/bin/view/Motion/Video loopbackFourLinuxLoopbackDevice
+ *    The Video loopback Loopback Device is no longer systematically maintained.
+ *    The project is a secondary project for the project "motion" found at
+ *    http://motion.sourceforge.net/ and
+ *    http://www.lavrsen.dk/twiki/bin/view/Motion/WebHome
+ *    and with the vloopback stored at
+ *    http://www.lavrsen.dk/twiki/bin/view/Motion/Video loopbackFourLinuxLoopbackDevice
  *
- *	CHANGE HISTORY
+ *    CHANGE HISTORY
  *
- *	UPDATED:	Jeroen Vreeken.
- *			Added locks for smp machines. UNTESTED!
- *			Made the driver much more cpu friendly by using
- *			a wait queue.
- *			Went from vmalloc to rvmalloc (yes, I stole the code
- *			like everybody else) and implemented mmap.
- *			Implemented VIDIOCGUNIT and removed size/palette checks
- *			in VIDIOCSYNC.
- *			Cleaned up a lot of code.
- *			Changed locks to semaphores.
- *			Disabled changing size while somebody is using mmap
- *			Changed mapped check to open check, also don't allow
- *			a open for write while somebody is reading.
- *			Added /proc support
- *			Set dumped count to zero at open.
- *			Modified /proc layout (added vloopbacks entry)
+ *    UPDATED:    Jeroen Vreeken.
+ *            Added locks for smp machines. UNTESTED!
+ *            Made the driver much more cpu friendly by using
+ *            a wait queue.
+ *            Went from vmalloc to rvmalloc (yes, I stole the code
+ *            like everybody else) and implemented mmap.
+ *            Implemented VIDIOCGUNIT and removed size/palette checks
+ *            in VIDIOCSYNC.
+ *            Cleaned up a lot of code.
+ *            Changed locks to semaphores.
+ *            Disabled changing size while somebody is using mmap
+ *            Changed mapped check to open check, also don't allow
+ *            a open for write while somebody is reading.
+ *            Added /proc support
+ *            Set dumped count to zero at open.
+ *            Modified /proc layout (added vloopbacks entry)
  *
- * 05.10.00 (MTS)	Added Linux 2.2 support
- * 06.10.00 (J Vreeken)	Fixed 2.2 support to make things work under 2.4 again.
- * 17.10.00 (J Vreeken)	Added zero copy mode
+ * 05.10.00 (MTS)    Added Linux 2.2 support
+ * 06.10.00 (J Vreeken)    Fixed 2.2 support to make things work under 2.4 again.
+ * 17.10.00 (J Vreeken)    Added zero copy mode
  * 19.10.00 (J Vreeken) Added SIGIO on device close.
  * 24.10.00 (J Vreeken) Modified 2.2 stuff and removed spinlock.h
- *			released 0.81
+ *            released 0.81
  * 27.10.00 (J Vreeken) Implemented poll
- *			released 0.82
+ *            released 0.82
  * 17.01.01 (J Vreeken) support for xawtv
- * 			Implemented VIDIOCGFBUF
- *			Additional checks on framebuffer freeing.
- *			released 0.83
- * 31.01.01 (J Vreeken)	Removed need for 'struct ioctl', use _IOC_SIZE() and
- *			IOC_IN instead.
- *			Change the ioctlnr passing to 'unsigned long int'
- *			Instead of just one byte.
- *			THIS BREAKS COMPATIBILITY WITH PREVIOUS VERSIONS!!! 
- * 29.06.01 (J Vreeken)	Added dev_offset module option
- *			Made vloopback_template sane
- *			Added double buffering support
- *			Made vloopback less verbose
- * 20.11.01	(tibit)	Made dev_offset option sane
- *			"Fixed" zerocopy mode by defining the ioctl 
- *			VIDIOCSINVALID. An application which provides data
- *			has to issue it when it encounters an error in
- *			ioctl processing. See dummy.c for examples.
- * 26.11.03	(Kenneth Lavrsen)
- *			released 0.91
- *			0.91 is the combination of the 0.90-tibit by
- *			Tilmann Bitterberg and an update of the Makefile by
- *			Roberto Carvajal.
- * 23.01.05	(W Brack)
- *			(don't know what happened to the comments for 0.92
- *			 and 0.93, but I tentatively named this one as 0.99)
- *			enhanced for linux-2.6, with #ifdef to keep it
- *			compatible with linux-2.4.  For linux versions
- *			> 2.5, I changed the memory management
- *			routines to the "more modern" way, most of it
- *			shamelessly copied from other drivers.  I also
- *			added in the code necessary to avoid the "videodev
- *			has no release callback" message when installing.
- *			For versions < 2.5, I updated the routines to be
- *			closer to several other drivers.
+ *             Implemented VIDIOCGFBUF
+ *            Additional checks on framebuffer freeing.
+ *            released 0.83
+ * 31.01.01 (J Vreeken)    Removed need for 'struct ioctl', use _IOC_SIZE() and
+ *            IOC_IN instead.
+ *            Change the ioctlnr passing to 'unsigned long int'
+ *            Instead of just one byte.
+ *            THIS BREAKS COMPATIBILITY WITH PREVIOUS VERSIONS!!! 
+ * 29.06.01 (J Vreeken)    Added dev_offset module option
+ *            Made vloopback_template sane
+ *            Added double buffering support
+ *            Made vloopback less verbose
+ * 20.11.01    (tibit)    Made dev_offset option sane
+ *            "Fixed" zerocopy mode by defining the ioctl 
+ *            VIDIOCSINVALID. An application which provides data
+ *            has to issue it when it encounters an error in
+ *            ioctl processing. See dummy.c for examples.
+ * 26.11.03    (Kenneth Lavrsen)
+ *            released 0.91
+ *            0.91 is the combination of the 0.90-tibit by
+ *            Tilmann Bitterberg and an update of the Makefile by
+ *            Roberto Carvajal.
+ * 23.01.05    (W Brack)
+ *            (don't know what happened to the comments for 0.92
+ *             and 0.93, but I tentatively named this one as 0.99)
+ *            enhanced for linux-2.6, with #ifdef to keep it
+ *            compatible with linux-2.4.  For linux versions
+ *            > 2.5, I changed the memory management
+ *            routines to the "more modern" way, most of it
+ *            shamelessly copied from other drivers.  I also
+ *            added in the code necessary to avoid the "videodev
+ *            has no release callback" message when installing.
+ *            For versions < 2.5, I updated the routines to be
+ *            closer to several other drivers.
  *
- * 04.02.05	(Angel Carpintero)
- *			Fixed version number to 0.93-pre1.
- *			Fixed warning for interruptible_sleep_on() deprecated and added 
- *			wait_event_interruptible compatible with 2.6.x and 2.7.
- *			Fixed memory manager for kernel version > 2.6.9.
+ * 04.02.05    (Angel Carpintero)
+ *            Fixed version number to 0.93-pre1.
+ *            Fixed warning for interruptible_sleep_on() deprecated and added 
+ *            wait_event_interruptible compatible with 2.6.x and 2.7.
+ *            Fixed memory manager for kernel version > 2.6.9.
  *
- * 07.02.05	(Kenneth Lavrsen)
- *			Changed version to 0.94.
- *			Released as formal released version
+ * 07.02.05    (Kenneth Lavrsen)
+ *            Changed version to 0.94.
+ *            Released as formal released version
  *
- * 20.02.05	(W Brack)
- *			Fixed error with wait_event_interruptible.
- *			Fixed crash when pipe source was stopped before dest.
+ * 20.02.05    (W Brack)
+ *            Fixed error with wait_event_interruptible.
+ *            Fixed crash when pipe source was stopped before dest.
  *
- * 20.02.05	(Angel Carpintero)     
- *			Added install and uninstall in Makefile.
+ * 20.02.05    (Angel Carpintero)     
+ *            Added install and uninstall in Makefile.
  *
  *
- * 25.04.05	(Angel Carpintero)
- *			Included Samuel Audet's patch, it checks if the input is already
- *			opened in write mode.
+ * 25.04.05    (Angel Carpintero)
+ *            Included Samuel Audet's patch, it checks if the input is already
+ *            opened in write mode.
  *
- * 02.05.05	(Kenneth Lavrsen)
- *			Released 0.95-snap2 formerly as 0.95
- *	
- * 10.05.05	(Angel Carpintero)
- *			Added MODULE_VERSION(), fixed create_pipes when video_register_device() returns
- *			-ENFILE . 
- *			Fix warnings about checking return value from copy_to_user() and copy_from_user() functions.
+ * 02.05.05    (Kenneth Lavrsen)
+ *            Released 0.95-snap2 formerly as 0.95
+ *    
+ * 10.05.05    (Angel Carpintero)
+ *            Added MODULE_VERSION(), fixed create_pipes when video_register_device() returns
+ *            -ENFILE . 
+ *            Fix warnings about checking return value from copy_to_user() and copy_from_user() functions.
  *
- * 14.11.05	(Angel Carpintero)
- *			Added <linux/version.h> that includes LINUX_VERSION_CODE and KERNEL_VERSION to fix 
- *			compilation agains kernel 2.6.14 , change version to 0.97-snap1
+ * 14.11.05    (Angel Carpintero)
+ *            Added <linux/version.h> that includes LINUX_VERSION_CODE and KERNEL_VERSION to fix 
+ *            compilation agains kernel 2.6.14 , change version to 0.97-snap1
  *
- * 19.12.05	(Angel Carpintero)
- *			Added to example option to choose between rgb24 or yuv420p palettes.
+ * 19.12.05    (Angel Carpintero)
+ *            Added to example option to choose between rgb24 or yuv420p palettes.
  *
- * 31.12.05	(Angel Carpintero)
- * 			Fixed examples, remove perror calls and add support to dummy.c for sysfs.
- * 			
- * 04.06.06	(Angel Carpintero)
- * 			Add module_param() for kernel > 2.5 because MODULE_PARAM() macro is obsolete.
+ * 31.12.05    (Angel Carpintero)
+ *             Fixed examples, remove perror calls and add support to dummy.c for sysfs.
+ *             
+ * 04.06.06    (Angel Carpintero)
+ *             Add module_param() for kernel > 2.5 because MODULE_PARAM() macro is obsolete.
  *
- * 17.06.06	(Angel Carpintero)
- *			Release version 1.0 with some fixes and code clean up. Added a Jack Bates contribution
- *			to allow build a kernel module in debian way.
+ * 17.06.06    (Angel Carpintero)
+ *            Release version 1.0 with some fixes and code clean up. Added a Jack Bates contribution
+ *            to allow build a kernel module in debian way.
  *
- * 26.06.06	(Angel Carpintero)
- *			Added some improvements in Makefile. Fix a problem to compile in Suse.
+ * 26.06.06    (Angel Carpintero)
+ *            Added some improvements in Makefile. Fix a problem to compile in Suse.
  *
  *
- * 02.11.06	(Angel Carpintero)
- * 			Make compatible with new kernel stable version 2.6.18, Many functions and declarations has
- * 			been moved to media/v42l-dev.h and remove from videodev.h/videodev2.h
+ * 02.11.06    (Angel Carpintero)
+ *            Make compatible with new kernel stable version 2.6.18, Many functions and declarations has
+ *            been moved to media/v42l-dev.h and remove from videodev.h/videodev2.h
  *
- * 18.01.07	(Angel Carpintero)	
- * 			Change -ENOIOCTLCMD by more appropiate error -ENOTTY.
- * 								
- * 18.05.08	(Angel Carpintero)
- * 			Release 1.1-rc1 as 1.1 stable working with 2.6.24
+ * 18.01.07    (Angel Carpintero)    
+ *            Change -ENOIOCTLCMD by more appropiate error -ENOTTY.
+ *                                 
+ * 18.05.08    (Angel Carpintero)
+ *            Release 1.1-rc1 as 1.1 stable working with 2.6.24
  *
- * 17.08.08	(Angel Carpintero)
- * 			kill_proc() deprecated ,pid API changed , type and owner not available in 							
- * 			video_device struct, added param debug.
+ * 17.08.08    (Angel Carpintero)
+ *            kill_proc() deprecated ,pid API changed , type and owner not available in                             
+ *            video_device struct, added param debug.
+ *
+ * 24.08.08    (Angel Carpintero)
+ *            Added compat_iotcl32 init in fopsl, replace tabs by 4 spaces in source code,
+ *            add number of buffers as module param.
  */
 
 
 #define VLOOPBACK_VERSION "1.2-trunk"
 
 /* Include files common to 2.4 and 2.6 versions */
-#include <linux/version.h>	/* >= 2.6.14 LINUX_VERSION_CODE */ 
+#include <linux/version.h>    /* >= 2.6.14 LINUX_VERSION_CODE */ 
 #include <linux/errno.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
@@ -167,12 +171,12 @@
  #include <asm/page.h> 
  #include <asm/pgtable.h>
  #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,10)
-  #ifndef	remap_pfn_range
-    #define	remap_pfn_range(a,b,c,d,e) \
-	 remap_page_range((a),(b),(c)<<PAGE_SHIFT,(d),(e))
+  #ifndef    remap_pfn_range
+    #define    remap_pfn_range(a,b,c,d,e) \
+     remap_page_range((a),(b),(c)<<PAGE_SHIFT,(d),(e))
   #endif
-  #ifndef	vmalloc_to_pfn
-    #define	vmalloc_to_pfn(a) page_to_pfn(vmalloc_to_page((a)))
+  #ifndef    vmalloc_to_pfn
+    #define    vmalloc_to_pfn(a) page_to_pfn(vmalloc_to_page((a)))
   #endif
  #endif
  #include <asm/uaccess.h>
@@ -185,7 +189,7 @@
  #include <asm/io.h>
 #endif
  
-#define VIDIOCSINVALID	_IO('v',BASE_VIDIOCPRIVATE+1)
+#define VIDIOCSINVALID    _IO('v',BASE_VIDIOCPRIVATE+1)
 
 #define verbose(format, arg...) if (printk_ratelimit()) \
         printk(KERN_INFO "[%s] %s: " format "\n" "", \
@@ -201,47 +205,48 @@
 #define LOG_VERBOSE   3
 
 struct vloopback_private {
-	int pipenr;
-	int in; /* bool , is being feed ? */
+    int pipenr;
+    int in; /* bool , is being feed ? */
 };
 
 typedef struct vloopback_private *priv_ptr;
 
 struct vloopback_pipe {
-	struct video_device *vloopin;
- 	struct video_device *vloopout;
-	char *buffer;
-	unsigned long buflength;
-	unsigned int width, height;
-	unsigned int palette;
-	unsigned long frameswrite;
-	unsigned long framesread;
-	unsigned long framesdumped;
-	unsigned int wopen;
-	unsigned int ropen;
-	struct semaphore lock;
-	wait_queue_head_t wait;
-	unsigned int frame;
+    struct video_device *vloopin;
+     struct video_device *vloopout;
+    char *buffer;
+    unsigned long buflength;
+    unsigned int width, height;
+    unsigned int palette;
+    unsigned long frameswrite;
+    unsigned long framesread;
+    unsigned long framesdumped;
+    unsigned int wopen;
+    unsigned int ropen;
+    struct semaphore lock;
+    wait_queue_head_t wait;
+    unsigned int frame;
 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,27)    
-	unsigned int pid;
+    unsigned int pid;
 #else
     struct pid *pid;    
 #endif    
-	unsigned int zerocopy;
-	unsigned long int ioctlnr;
-	unsigned int invalid_ioctl; /* 0 .. none invalid; 1 .. invalid */
-	unsigned int ioctllength;
-	char *ioctldata;
-	char *ioctlretdata;
+    unsigned int zerocopy;
+    unsigned long int ioctlnr;
+    unsigned int invalid_ioctl; /* 0 .. none invalid; 1 .. invalid */
+    unsigned int ioctllength;
+    char *ioctldata;
+    char *ioctlretdata;
 };
 
 #define MAX_PIPES 16
-#define	N_BUFFS	2	/* Number of buffers used for pipes */
+#define N_BUFFS    2    /* Number of buffers used for pipes */
 
 static struct vloopback_pipe *loops[MAX_PIPES];
 static int nr_o_pipes = 0;
 static int pipes = -1;
 static int spares = 0;
+static unsigned int num_buffers = N_BUFFS;
 static int pipesused = 0;
 static int dev_offset = -1;
 static unsigned int debug = LOG_NODEBUG;
@@ -260,62 +265,62 @@
 {
     unsigned long kva;
 
-	kva = (unsigned long)page_address(vmalloc_to_page((void *)adr));
-	kva |= adr & (PAGE_SIZE-1); /* restore the offset */
-	return __pa(kva);
+    kva = (unsigned long)page_address(vmalloc_to_page((void *)adr));
+    kva |= adr & (PAGE_SIZE-1); /* restore the offset */
+    return __pa(kva);
 }
 #endif
 
 static void *rvmalloc(unsigned long size)
 {
 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
-	struct page *page;
+    struct page *page;
 #endif
-	void *mem;
-	unsigned long adr;
+    void *mem;
+    unsigned long adr;
 
-	size = PAGE_ALIGN(size);
-	mem = vmalloc_32(size);
-	if (!mem)
-		return NULL;
-	memset(mem, 0, size); /* Clear the ram out, no junk to the user */
-	adr = (unsigned long) mem;
-	while (size > 0) {
+    size = PAGE_ALIGN(size);
+    mem = vmalloc_32(size);
+    if (!mem)
+        return NULL;
+    memset(mem, 0, size); /* Clear the ram out, no junk to the user */
+    adr = (unsigned long) mem;
+    while (size > 0) {
 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
-		page = vmalloc_to_page((void *)adr);
-		mem_map_reserve(page);
+        page = vmalloc_to_page((void *)adr);
+        mem_map_reserve(page);
 #else
-		SetPageReserved(vmalloc_to_page((void *)adr));
+        SetPageReserved(vmalloc_to_page((void *)adr));
 #endif
-		adr += PAGE_SIZE;
-		size -= PAGE_SIZE;
-	}
+        adr += PAGE_SIZE;
+        size -= PAGE_SIZE;
+    }
 
-	return mem;
+    return mem;
 }
 
 static void rvfree(void *mem, unsigned long size)
 {
 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
-	struct page *page;
+    struct page *page;
 #endif
-	unsigned long adr;
+    unsigned long adr;
 
-	if (!mem)
-		return;
+    if (!mem)
+        return;
 
-	adr = (unsigned long) mem;
-	while ((long) size > 0) {
+    adr = (unsigned long) mem;
+    while ((long) size > 0) {
 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
-		page = vmalloc_to_page((void *)adr);
-		mem_map_unreserve(page);
+        page = vmalloc_to_page((void *)adr);
+        mem_map_unreserve(page);
 #else
-		ClearPageReserved(vmalloc_to_page((void *)adr));
+        ClearPageReserved(vmalloc_to_page((void *)adr));
 #endif
-		adr += PAGE_SIZE;
-		size -= PAGE_SIZE;
-	}
-	vfree(mem);
+        adr += PAGE_SIZE;
+        size -= PAGE_SIZE;
+    }
+    vfree(mem);
 }
 
 
@@ -323,14 +328,14 @@
 
 static int fake_ioctl(int nr, unsigned long int cmd, void *arg)
 {
-	unsigned long fw;
+    unsigned long fw;
 
     if (debug > LOG_NODEBUG)
         info("Video loopback %d cmd %lu", nr, cmd);
 
-	loops[nr]->ioctlnr = cmd;
-	memcpy(loops[nr]->ioctldata, arg, _IOC_SIZE(cmd));
-	loops[nr]->ioctllength = _IOC_SIZE(cmd);
+    loops[nr]->ioctlnr = cmd;
+    memcpy(loops[nr]->ioctldata, arg, _IOC_SIZE(cmd));
+    loops[nr]->ioctllength = _IOC_SIZE(cmd);
 
 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,27)
     kill_proc(loops[nr]->pid, SIGIO, 1);    /* Signal the pipe feeder */
@@ -339,59 +344,59 @@
 #endif
 
 #if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)
-	fw = loops[nr]->frameswrite;
-	wait_event_interruptible(loops[nr]->wait, fw != loops[nr]->frameswrite);
+    fw = loops[nr]->frameswrite;
+    wait_event_interruptible(loops[nr]->wait, fw != loops[nr]->frameswrite);
 #else
-	interruptible_sleep_on(&loops[nr]->wait);
-#endif	
-	if (cmd & IOC_IN) {
-		if (memcmp (arg, loops[nr]->ioctlretdata, _IOC_SIZE(cmd)))
-			return 1;
-	} else {
-		memcpy (arg, loops[nr]->ioctlretdata, _IOC_SIZE(cmd));
-	}
-	return 0;
+    interruptible_sleep_on(&loops[nr]->wait);
+#endif    
+    if (cmd & IOC_IN) {
+        if (memcmp (arg, loops[nr]->ioctlretdata, _IOC_SIZE(cmd)))
+            return 1;
+    } else {
+        memcpy (arg, loops[nr]->ioctlretdata, _IOC_SIZE(cmd));
+    }
+    return 0;
 }
 
 static int vloopback_open(struct inode *inod, struct file *f)
-{	
-	struct video_device *loopdev = video_devdata(f);
-	priv_ptr ptr = (priv_ptr)loopdev->priv;
-	int nr = ptr->pipenr;
+{    
+    struct video_device *loopdev = video_devdata(f);
+    priv_ptr ptr = (priv_ptr)loopdev->priv;
+    int nr = ptr->pipenr;
 
     if (debug > LOG_NODEBUG)
         info("Video loopback %d", nr);    
 
-	/* Only allow a output to be opened if there is someone feeding
-	 * the pipe.
-	 */
-	if (!ptr->in) {
-		if (loops[nr]->buffer == NULL) 
-			return -EINVAL;
-		
-		loops[nr]->framesread = 0;
-		loops[nr]->ropen = 1;
-	} else {
-		if (loops[nr]->ropen || loops[nr]->wopen) 
-			return -EBUSY;
+    /* Only allow a output to be opened if there is someone feeding
+     * the pipe.
+     */
+    if (!ptr->in) {
+        if (loops[nr]->buffer == NULL) 
+            return -EINVAL;
+        
+        loops[nr]->framesread = 0;
+        loops[nr]->ropen = 1;
+    } else {
+        if (loops[nr]->ropen || loops[nr]->wopen) 
+            return -EBUSY;
 
-		loops[nr]->framesdumped = 0;
-		loops[nr]->frameswrite = 0;
-		loops[nr]->wopen = 1;
-		loops[nr]->zerocopy = 0;
-		loops[nr]->ioctlnr = -1;
-		pipesused++;
-		if (nr_o_pipes-pipesused<spares) {
-			if (!create_pipe(nr_o_pipes)) {
-				info("Creating extra spare pipe");
-				info("Loopback %d registered, input: video%d, output: video%d",
-				    nr_o_pipes,
-				    loops[nr_o_pipes]->vloopin->minor,
-				    loops[nr_o_pipes]->vloopout->minor
-				);
-				nr_o_pipes++;
-			}
-		}
+        loops[nr]->framesdumped = 0;
+        loops[nr]->frameswrite = 0;
+        loops[nr]->wopen = 1;
+        loops[nr]->zerocopy = 0;
+        loops[nr]->ioctlnr = -1;
+        pipesused++;
+        if (nr_o_pipes-pipesused<spares) {
+            if (!create_pipe(nr_o_pipes)) {
+                info("Creating extra spare pipe");
+                info("Loopback %d registered, input: video%d, output: video%d",
+                    nr_o_pipes,
+                    loops[nr_o_pipes]->vloopin->minor,
+                    loops[nr_o_pipes]->vloopout->minor
+                );
+                nr_o_pipes++;
+            }
+        }
 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,27)
         loops[nr]->pid = current->pid;
 #else
@@ -402,238 +407,243 @@
 
         if (debug > LOG_NODEBUG)
             info("Current pid %d", current->pid);
-	}
-	return 0;
+    }
+    return 0;
 }
 
 static int vloopback_release(struct inode * inod, struct file *f)
 {
-	struct video_device *loopdev = video_devdata(f);
-	priv_ptr ptr = (priv_ptr)loopdev->priv;
-	int nr = ptr->pipenr;
+    struct video_device *loopdev = video_devdata(f);
+    priv_ptr ptr = (priv_ptr)loopdev->priv;
+    int nr = ptr->pipenr;
 
     if (debug > LOG_NODEBUG)
         info("Video loopback %d", nr);
 
-	if (ptr->in) {
-		down(&loops[nr]->lock);
-		if (loops[nr]->buffer && !loops[nr]->ropen) {
-			rvfree(loops[nr]->buffer, loops[nr]->buflength * N_BUFFS);
-			loops[nr]->buffer = NULL;
-		}
-		up(&loops[nr]->lock);
-		loops[nr]->frameswrite++;
-		if (waitqueue_active(&loops[nr]->wait))
-			wake_up(&loops[nr]->wait);
+    if (ptr->in) {
+        down(&loops[nr]->lock);
+        if (loops[nr]->buffer && !loops[nr]->ropen) {
+            rvfree(loops[nr]->buffer, loops[nr]->buflength * num_buffers);
+            loops[nr]->buffer = NULL;
+        }
+
+        up(&loops[nr]->lock);
+        loops[nr]->frameswrite++;
+        
+        if (waitqueue_active(&loops[nr]->wait))
+            wake_up(&loops[nr]->wait);
 
-		loops[nr]->width = 0;
-		loops[nr]->height = 0;
-		loops[nr]->palette = 0;
-		loops[nr]->wopen = 0;
-		pipesused--;
-	} else {
-		down(&loops[nr]->lock);
-		if (loops[nr]->buffer && !loops[nr]->wopen) {
-			rvfree(loops[nr]->buffer, loops[nr]->buflength * N_BUFFS);
-			loops[nr]->buffer = NULL;
-		}
-		up(&loops[nr]->lock);
-		loops[nr]->ropen = 0;
-		if (loops[nr]->zerocopy && loops[nr]->buffer) {
-			loops[nr]->ioctlnr = 0;
-			loops[nr]->ioctllength = 0;
+        loops[nr]->width = 0;
+        loops[nr]->height = 0;
+        loops[nr]->palette = 0;
+        loops[nr]->wopen = 0;
+        pipesused--;
+    } else {
+        down(&loops[nr]->lock);
+
+        if (loops[nr]->buffer && !loops[nr]->wopen) {
+            rvfree(loops[nr]->buffer, loops[nr]->buflength * num_buffers);
+            loops[nr]->buffer = NULL;
+        }
+
+        up(&loops[nr]->lock);
+        loops[nr]->ropen = 0;
+
+        if (loops[nr]->zerocopy && loops[nr]->buffer) {
+            loops[nr]->ioctlnr = 0;
+            loops[nr]->ioctllength = 0;
 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,27)
             kill_proc(loops[nr]->pid, SIGIO, 1);
 #else
             kill_pid(loops[nr]->pid, SIGIO, 1);
 #endif            
-		}
-	}
+        }
+    }
 
-	return 0;
+    return 0;
 }
 
 static ssize_t vloopback_write(struct file *f, const char *buf,
                size_t count, loff_t *offset)
 {
-	struct video_device *loopdev = video_devdata(f);
-	priv_ptr ptr = (priv_ptr)loopdev->priv;
-	int nr = ptr->pipenr;
-	unsigned long realcount = count;
+    struct video_device *loopdev = video_devdata(f);
+    priv_ptr ptr = (priv_ptr)loopdev->priv;
+    int nr = ptr->pipenr;
+    unsigned long realcount = count;
 
     if (debug > LOG_IOCTL)
         info("Video loopback %d", nr);
 
-	if (!ptr->in)
-		return -EINVAL;
+    if (!ptr->in)
+        return -EINVAL;
 
-	if (loops[nr]->zerocopy)
-		return -EINVAL;
-	
-	if (loops[nr]->buffer == NULL) 
-		return -EINVAL;
-	
-	/* Anybody want some pictures??? */
-	if (!waitqueue_active(&loops[nr]->wait)) {
-		loops[nr]->framesdumped++;
-		return realcount;
-	}
-	
-	down(&loops[nr]->lock);
-	if (!loops[nr]->buffer) {
-		up(&loops[nr]->lock);
-		return -EINVAL;
-	}
+    if (loops[nr]->zerocopy)
+        return -EINVAL;
+    
+    if (loops[nr]->buffer == NULL) 
+        return -EINVAL;
+    
+    /* Anybody want some pictures??? */
+    if (!waitqueue_active(&loops[nr]->wait)) {
+        loops[nr]->framesdumped++;
+        return realcount;
+    }
+    
+    down(&loops[nr]->lock);
+    if (!loops[nr]->buffer) {
+        up(&loops[nr]->lock);
+        return -EINVAL;
+    }
 
-	if (realcount > loops[nr]->buflength) {
-		realcount = loops[nr]->buflength;
-		info("Too much data for Video loopback %d ! Only %ld bytes used.", 
+    if (realcount > loops[nr]->buflength) {
+        realcount = loops[nr]->buflength;
+        info("Too much data for Video loopback %d ! Only %ld bytes used.", 
              nr, realcount);
-	}
-	
-	if (copy_from_user(loops[nr]->buffer + loops[nr]->frame * loops[nr]->buflength, 
+    }
+    
+    if (copy_from_user(loops[nr]->buffer + loops[nr]->frame * loops[nr]->buflength, 
                        buf, realcount)) 
         return -EFAULT;
 
-	loops[nr]->frame = 0;
-	up(&loops[nr]->lock);
+    loops[nr]->frame = 0;
+    up(&loops[nr]->lock);
 
-	loops[nr]->frameswrite++;
-	wake_up(&loops[nr]->wait);
+    loops[nr]->frameswrite++;
+    wake_up(&loops[nr]->wait);
 
-	return realcount;
+    return realcount;
 }
 
 static ssize_t vloopback_read(struct file * f, char * buf, size_t count, 
                loff_t *offset)
 {
-	struct video_device *loopdev = video_devdata(f);
-	priv_ptr ptr = (priv_ptr)loopdev->priv;
-	int nr = ptr->pipenr;
-	unsigned long realcount = count;
+    struct video_device *loopdev = video_devdata(f);
+    priv_ptr ptr = (priv_ptr)loopdev->priv;
+    int nr = ptr->pipenr;
+    unsigned long realcount = count;
 
     if (debug > LOG_IOCTL)
         info("Video loopback %d", nr);
 
-	if (loops[nr]->zerocopy) {
-		if (ptr->in) {
-			if (realcount > loops[nr]->ioctllength + sizeof(unsigned long int))
-				realcount = loops[nr]->ioctllength + sizeof(unsigned long int);
+    if (loops[nr]->zerocopy) {
+        if (ptr->in) {
+            if (realcount > loops[nr]->ioctllength + sizeof(unsigned long int))
+                realcount = loops[nr]->ioctllength + sizeof(unsigned long int);
 
-			if (copy_to_user(buf , &loops[nr]->ioctlnr, sizeof(unsigned long int)))
-				return -EFAULT;
+            if (copy_to_user(buf , &loops[nr]->ioctlnr, sizeof(unsigned long int)))
+                return -EFAULT;
 
-			if (copy_to_user(buf + sizeof(unsigned long int), loops[nr]->ioctldata, 
-				             realcount - sizeof(unsigned long int)))
-				return -EFAULT;	
+            if (copy_to_user(buf + sizeof(unsigned long int), loops[nr]->ioctldata, 
+                             realcount - sizeof(unsigned long int)))
+                return -EFAULT;    
 
-			if (loops[nr]->ioctlnr == 0)
-				loops[nr]->ioctlnr = -1;
+            if (loops[nr]->ioctlnr == 0)
+                loops[nr]->ioctlnr = -1;
 
-			return realcount;
-		} else {
-			struct video_window vidwin;
-			struct video_mmap vidmmap;
-			struct video_picture vidpic;
-			
-			fake_ioctl(nr, VIDIOCGWIN, &vidwin);
-			fake_ioctl(nr, VIDIOCGPICT, &vidpic);
+            return realcount;
+        } else {
+            struct video_window vidwin;
+            struct video_mmap vidmmap;
+            struct video_picture vidpic;
+            
+            fake_ioctl(nr, VIDIOCGWIN, &vidwin);
+            fake_ioctl(nr, VIDIOCGPICT, &vidpic);
 
-			vidmmap.height = vidwin.height;
-			vidmmap.width = vidwin.width;
-			vidmmap.format = vidpic.palette;
-			vidmmap.frame = 0;
+            vidmmap.height = vidwin.height;
+            vidmmap.width = vidwin.width;
+            vidmmap.format = vidpic.palette;
+            vidmmap.frame = 0;
 
-			if (fake_ioctl(nr, VIDIOCMCAPTURE, &vidmmap))
-				return 0;
+            if (fake_ioctl(nr, VIDIOCMCAPTURE, &vidmmap))
+                return 0;
 
-			if (fake_ioctl(nr, VIDIOCSYNC, &vidmmap))
-				return 0;
+            if (fake_ioctl(nr, VIDIOCSYNC, &vidmmap))
+                return 0;
 
-			realcount = vidwin.height * vidwin.width * vidpic.depth;
-		}
-	}
+            realcount = vidwin.height * vidwin.width * vidpic.depth;
+        }
+    }
 
-	if (ptr->in)
-		return -EINVAL;
+    if (ptr->in)
+        return -EINVAL;
 
-	if (realcount > loops[nr]->buflength) {
-		realcount = loops[nr]->buflength;
-		info("Not so much data in buffer! for Video loopback %d", nr);
-	}
+    if (realcount > loops[nr]->buflength) {
+        realcount = loops[nr]->buflength;
+        info("Not so much data in buffer! for Video loopback %d", nr);
+    }
 
-	if (!loops[nr]->zerocopy) {
+    if (!loops[nr]->zerocopy) {
 #if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)
-		unsigned long fw = loops[nr]->frameswrite;
-		
-		wait_event_interruptible(loops[nr]->wait, fw != loops[nr]->frameswrite);
+        unsigned long fw = loops[nr]->frameswrite;
+        
+        wait_event_interruptible(loops[nr]->wait, fw != loops[nr]->frameswrite);
 #else
-		interruptible_sleep_on(&loops[nr]->wait);
+        interruptible_sleep_on(&loops[nr]->wait);
 #endif
-	}
+    }
 
-	down(&loops[nr]->lock);
-	if (!loops[nr]->buffer) {
-		up(&loops[nr]->lock);
-		return 0;
-	}
+    down(&loops[nr]->lock);
+    if (!loops[nr]->buffer) {
+        up(&loops[nr]->lock);
+        return 0;
+    }
 
-	if (copy_to_user(buf, loops[nr]->buffer, realcount))
-		return -EFAULT;
+    if (copy_to_user(buf, loops[nr]->buffer, realcount))
+        return -EFAULT;
 
-	up(&loops[nr]->lock);
+    up(&loops[nr]->lock);
 
-	loops[nr]->framesread++;
-	return realcount;
+    loops[nr]->framesread++;
+    return realcount;
 }
 
 static int vloopback_mmap(struct file *f, struct vm_area_struct *vma)
 {
-	struct video_device *loopdev = video_devdata(f);
-	priv_ptr ptr = (priv_ptr)loopdev->priv;
-	int nr = ptr->pipenr;
-	unsigned long start = (unsigned long)vma->vm_start;
-	long size = vma->vm_end - vma->vm_start;
-	unsigned long page, pos;
+    struct video_device *loopdev = video_devdata(f);
+    priv_ptr ptr = (priv_ptr)loopdev->priv;
+    int nr = ptr->pipenr;
+    unsigned long start = (unsigned long)vma->vm_start;
+    long size = vma->vm_end - vma->vm_start;
+    unsigned long page, pos;
 
     if (debug > LOG_NODEBUG)
         info("Video loopback %d", nr);
 
-	down(&loops[nr]->lock);
+    down(&loops[nr]->lock);
 
-	if (ptr->in) {
-		loops[nr]->zerocopy = 1;
+    if (ptr->in) {
+        loops[nr]->zerocopy = 1;
 
-		if (loops[nr]->ropen) {
-			info("Can't change size while opened for read in Video loopback %d",
+        if (loops[nr]->ropen) {
+            info("Can't change size while opened for read in Video loopback %d",
                  nr);
-			up(&loops[nr]->lock);
-			return -EINVAL;
-		}
+            up(&loops[nr]->lock);
+            return -EINVAL;
+        }
 
-		if (!size) {
-			up(&loops[nr]->lock);
+        if (!size) {
+            up(&loops[nr]->lock);
             info("Invalid size Video loopback %d", nr);
-			return -EINVAL;
-		}
+            return -EINVAL;
+        }
 
-		if (loops[nr]->buffer)
-			rvfree(loops[nr]->buffer, loops[nr]->buflength * N_BUFFS);
+        if (loops[nr]->buffer)
+            rvfree(loops[nr]->buffer, loops[nr]->buflength * num_buffers);
 
-		loops[nr]->buflength = size;
-		loops[nr]->buffer = rvmalloc(loops[nr]->buflength * N_BUFFS);
-	}
+        loops[nr]->buflength = size;
+        loops[nr]->buffer = rvmalloc(loops[nr]->buflength * num_buffers);
+    }
 
     if (loops[nr]->buffer == NULL) {
-		up(&loops[nr]->lock);
+        up(&loops[nr]->lock);
         return -EINVAL;
-	}
+    }
 
-    if (size > (((N_BUFFS * loops[nr]->buflength) + PAGE_SIZE - 1) 
+    if (size > (((num_buffers * loops[nr]->buflength) + PAGE_SIZE - 1) 
         & ~(PAGE_SIZE - 1))) {
-		up(&loops[nr]->lock);
+        up(&loops[nr]->lock);
         return -EINVAL;
-	}
+    }
 
     pos = (unsigned long)loops[nr]->buffer;
 
@@ -642,42 +652,42 @@
         page = kvirt_to_pa(pos);
         if (remap_page_range(vma,start, page, PAGE_SIZE, PAGE_SHARED)) {
 #else
-		page = vmalloc_to_pfn((void *)pos);
-		if (remap_pfn_range(vma, start, page, PAGE_SIZE, PAGE_SHARED)) {
+        page = vmalloc_to_pfn((void *)pos);
+        if (remap_pfn_range(vma, start, page, PAGE_SIZE, PAGE_SHARED)) {
 #endif
-		    up(&loops[nr]->lock);
+            up(&loops[nr]->lock);
             return -EAGAIN;
-		}
+        }
         start += PAGE_SIZE;
         pos += PAGE_SIZE;
-		size -= PAGE_SIZE;
+        size -= PAGE_SIZE;
     }
 
-	up(&loops[nr]->lock);
+    up(&loops[nr]->lock);
 
-	return 0;
+    return 0;
 }
 
 static int vloopback_ioctl(struct inode *inod, struct file *f, unsigned int cmd, 
            unsigned long arg)
 {
-	struct video_device *loopdev = video_devdata(f);
-	priv_ptr ptr = (priv_ptr)loopdev->priv;
-	int nr = ptr->pipenr;
-	int i;
+    struct video_device *loopdev = video_devdata(f);
+    priv_ptr ptr = (priv_ptr)loopdev->priv;
+    int nr = ptr->pipenr;
+    int i;
 
     if (debug > LOG_NODEBUG)
         info("Video loopback %d cmd %u", nr, cmd);
 
-	if (loops[nr]->zerocopy) {
-		if (!ptr->in) {
-			loops[nr]->ioctlnr = cmd;
-			loops[nr]->ioctllength = _IOC_SIZE(cmd);
-			/* info("DEBUG: vl_ioctl: !loop->in"); */
-			/* info("DEBUG: vl_ioctl: cmd %lu", cmd); */
-			/* info("DEBUG: vl_ioctl: len %lu", loops[nr]->ioctllength); */
-			if (copy_from_user(loops[nr]->ioctldata, (void*)arg, _IOC_SIZE(cmd)))
-				return -EFAULT;
+    if (loops[nr]->zerocopy) {
+        if (!ptr->in) {
+            loops[nr]->ioctlnr = cmd;
+            loops[nr]->ioctllength = _IOC_SIZE(cmd);
+            /* info("DEBUG: vl_ioctl: !loop->in"); */
+            /* info("DEBUG: vl_ioctl: cmd %lu", cmd); */
+            /* info("DEBUG: vl_ioctl: len %lu", loops[nr]->ioctllength); */
+            if (copy_from_user(loops[nr]->ioctldata, (void*)arg, _IOC_SIZE(cmd)))
+                return -EFAULT;
 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,27)
             kill_proc(loops[nr]->pid, SIGIO, 1);
 #else
@@ -685,410 +695,414 @@
 #endif            
 
 #if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)
-			wait_event_interruptible(loops[nr]->wait, loops[nr]->ioctlnr == -1);
+            wait_event_interruptible(loops[nr]->wait, loops[nr]->ioctlnr == -1);
 #else
-			interruptible_sleep_on(&loops[nr]->wait);
-#endif			
-			
-			if (loops[nr]->invalid_ioctl) {
-				info ("There was an invalid ioctl in Video loopback %d", nr);
+            interruptible_sleep_on(&loops[nr]->wait);
+#endif            
+            
+            if (loops[nr]->invalid_ioctl) {
+                info ("There was an invalid ioctl in Video loopback %d", nr);
                 loops[nr]->invalid_ioctl = 0;
-				return -ENOTTY;
-			}
+                return -ENOTTY;
+            }
 
-			if (cmd & IOC_IN && !(cmd & IOC_OUT)) {
-				//info("DEBUG: vl_ioctl: cmd & IOC_IN 1"); 
-				if (memcmp(loops[nr]->ioctlretdata, loops[nr]->ioctldata, _IOC_SIZE(cmd))) 
-					return -EINVAL;
-				
-			 	//info("DEBUG: vl_ioctl: cmd & IOC_IN 2"); 
-				return 0;
-			} else {
-				if (copy_to_user((void*)arg, loops[nr]->ioctlretdata, _IOC_SIZE(cmd)))
-					return -EFAULT;
-				//info("DEBUG: vl_ioctl: !(cmd & IOC_IN) 1");
-				return 0;
-			}
-		} else {
-			if ((loops[nr]->ioctlnr != cmd) && (cmd != (VIDIOCSINVALID))) {
-				/* wrong ioctl */
-				info("Wrong IOCTL %u in Video loopback %d", cmd, nr);
+            if (cmd & IOC_IN && !(cmd & IOC_OUT)) {
+                //info("DEBUG: vl_ioctl: cmd & IOC_IN 1"); 
+                if (memcmp(loops[nr]->ioctlretdata, loops[nr]->ioctldata, _IOC_SIZE(cmd))) 
+                    return -EINVAL;
+                
+                 //info("DEBUG: vl_ioctl: cmd & IOC_IN 2"); 
+                return 0;
+            } else {
+                if (copy_to_user((void*)arg, loops[nr]->ioctlretdata, _IOC_SIZE(cmd)))
+                    return -EFAULT;
+                //info("DEBUG: vl_ioctl: !(cmd & IOC_IN) 1");
                 return 0;
-			}
+            }
+        } else {
+            if ((loops[nr]->ioctlnr != cmd) && (cmd != (VIDIOCSINVALID))) {
+                /* wrong ioctl */
+                info("Wrong IOCTL %u in Video loopback %d", cmd, nr);
+                return 0;
+            }
 
-			if (cmd == VIDIOCSINVALID) {
-				loops[nr]->invalid_ioctl = 1;
-			} else if (copy_from_user(loops[nr]->ioctlretdata, 
+            if (cmd == VIDIOCSINVALID) {
+                loops[nr]->invalid_ioctl = 1;
+            } else if (copy_from_user(loops[nr]->ioctlretdata, 
                       (void*)arg, loops[nr]->ioctllength)) {
-				return -EFAULT;
-			}
+                return -EFAULT;
+            }
 
-			loops[nr]->ioctlnr = -1;
+            loops[nr]->ioctlnr = -1;
 
-			if (waitqueue_active(&loops[nr]->wait))
-				wake_up(&loops[nr]->wait);
+            if (waitqueue_active(&loops[nr]->wait))
+                wake_up(&loops[nr]->wait);
 
-			return 0;
-		}
-	}
+            return 0;
+        }
+    }
 
-	switch(cmd)
-	{
-	/* Get capabilities */
-	case VIDIOCGCAP:
-	{
-		struct video_capability b;
-		if (ptr->in) {
-			sprintf(b.name, "Video loopback %d input", nr);
-			b.type = 0;
-		} else {
-			sprintf(b.name, "Video loopback %d output", nr);
-			b.type = VID_TYPE_CAPTURE;
-		}
+    switch(cmd)
+    {
+    /* Get capabilities */
+    case VIDIOCGCAP:
+    {
+        struct video_capability b;
+        if (ptr->in) {
+            sprintf(b.name, "Video loopback %d input", nr);
+            b.type = 0;
+        } else {
+            sprintf(b.name, "Video loopback %d output", nr);
+            b.type = VID_TYPE_CAPTURE;
+        }
 
-		b.channels = 1;
-		b.audios = 0;
-		b.maxwidth = loops[nr]->width;
-		b.maxheight = loops[nr]->height;
-		b.minwidth = 20;
-		b.minheight = 20;
+        b.channels = 1;
+        b.audios = 0;
+        b.maxwidth = loops[nr]->width;
+        b.maxheight = loops[nr]->height;
+        b.minwidth = 20;
+        b.minheight = 20;
 
-		if (copy_to_user((void*)arg, &b, sizeof(b)))
-			return -EFAULT;
+        if (copy_to_user((void*)arg, &b, sizeof(b)))
+            return -EFAULT;
 
-		return 0;
-	}
-	/* Get channel info (sources) */
-	case VIDIOCGCHAN:
-	{
-		struct video_channel v;
-		if (copy_from_user(&v, (void*)arg, sizeof(v)))
-			return -EFAULT;
+        return 0;
+    }
+    /* Get channel info (sources) */
+    case VIDIOCGCHAN:
+    {
+        struct video_channel v;
+        if (copy_from_user(&v, (void*)arg, sizeof(v)))
+            return -EFAULT;
 
-		if (v.channel != 0) {
-			info("VIDIOCGCHAN: Invalid Channel, was %d", v.channel);
-			v.channel = 0;
-				//return -EINVAL;
-		}
+        if (v.channel != 0) {
+            info("VIDIOCGCHAN: Invalid Channel, was %d", v.channel);
+            v.channel = 0;
+                //return -EINVAL;
+        }
 
-		v.flags = 0;
-		v.tuners = 0;
-		v.norm = 0;
-		v.type = VIDEO_TYPE_CAMERA;
-		/*strcpy(v.name, "Loopback"); -- tibit */
-		strcpy(v.name, "Composite1");
+        v.flags = 0;
+        v.tuners = 0;
+        v.norm = 0;
+        v.type = VIDEO_TYPE_CAMERA;
+        /*strcpy(v.name, "Loopback"); -- tibit */
+        strcpy(v.name, "Composite1");
 
-		if (copy_to_user((void*)arg, &v, sizeof(v)))
-			return -EFAULT;
+        if (copy_to_user((void*)arg, &v, sizeof(v)))
+            return -EFAULT;
 
-		return 0;
-	}
-	/* Set channel 	*/
-	case VIDIOCSCHAN:
-	{
-		int v;
+        return 0;
+    }
+    /* Set channel     */
+    case VIDIOCSCHAN:
+    {
+        int v;
 
-		if (copy_from_user(&v, (void*)arg, sizeof(v)))
-			return -EFAULT;
+        if (copy_from_user(&v, (void*)arg, sizeof(v)))
+            return -EFAULT;
 
-		if (v != 0) {
-			info("VIDIOCSCHAN: Invalid Channel, was %d", v);
-			return -EINVAL;
-		}
+        if (v != 0) {
+            info("VIDIOCSCHAN: Invalid Channel, was %d", v);
+            return -EINVAL;
+        }
 
-		return 0;
-	}
-	/* Get tuner abilities */
-	case VIDIOCGTUNER:
-	{
-		struct video_tuner v;
+        return 0;
+    }
+    /* Get tuner abilities */
+    case VIDIOCGTUNER:
+    {
+        struct video_tuner v;
 
-		if (copy_from_user(&v, (void*)arg, sizeof(v)) != 0)
-			return -EFAULT;
+        if (copy_from_user(&v, (void*)arg, sizeof(v)) != 0)
+            return -EFAULT;
 
-		if (v.tuner) {
-			info("VIDIOCGTUNER: Invalid Tuner, was %d", v.tuner);
-			return -EINVAL;
-		}
+        if (v.tuner) {
+            info("VIDIOCGTUNER: Invalid Tuner, was %d", v.tuner);
+            return -EINVAL;
+        }
 
-		strcpy(v.name, "Format");
-		v.rangelow = 0;
-		v.rangehigh = 0;
-		v.flags = 0;
-		v.mode = VIDEO_MODE_AUTO;
+        strcpy(v.name, "Format");
+        v.rangelow = 0;
+        v.rangehigh = 0;
+        v.flags = 0;
+        v.mode = VIDEO_MODE_AUTO;
 
-		if (copy_to_user((void*)arg,&v, sizeof(v)) != 0)
-			return -EFAULT;
+        if (copy_to_user((void*)arg,&v, sizeof(v)) != 0)
+            return -EFAULT;
 
-		return 0;
-	}
-	/* Get picture properties */
-	case VIDIOCGPICT:
-	{
-		struct video_picture p;
+        return 0;
+    }
+    /* Get picture properties */
+    case VIDIOCGPICT:
+    {
+        struct video_picture p;
 
-		p.colour = 0x8000;
-		p.hue = 0x8000;
-		p.brightness = 0x8000;
-		p.contrast = 0x8000;
-		p.whiteness = 0x8000;
-		p.depth = 0x8000;
-		p.palette = loops[nr]->palette;
+        p.colour = 0x8000;
+        p.hue = 0x8000;
+        p.brightness = 0x8000;
+        p.contrast = 0x8000;
+        p.whiteness = 0x8000;
+        p.depth = 0x8000;
+        p.palette = loops[nr]->palette;
 
-		if (copy_to_user((void*)arg, &p, sizeof(p)))
-			return -EFAULT;
+        if (copy_to_user((void*)arg, &p, sizeof(p)))
+            return -EFAULT;
 
-		return 0;
-	}
-	/* Set picture properties */
-	case VIDIOCSPICT:
-	{
-		struct video_picture p;
+        return 0;
+    }
+    /* Set picture properties */
+    case VIDIOCSPICT:
+    {
+        struct video_picture p;
 
-		if (copy_from_user(&p, (void*)arg, sizeof(p)))
-			return -EFAULT;
+        if (copy_from_user(&p, (void*)arg, sizeof(p)))
+            return -EFAULT;
 
-		if (!ptr->in) {
-			if (p.palette != loops[nr]->palette)
-				return -EINVAL;
-		} else {
-			loops[nr]->palette = p.palette;
+        if (!ptr->in) {
+            if (p.palette != loops[nr]->palette)
+                return -EINVAL;
+        } else {
+            loops[nr]->palette = p.palette;
         }
 
-		return 0;
-	}
-	/* Get the video overlay window */
-	case VIDIOCGWIN:
-	{
-		struct video_window vw;
+        return 0;
+    }
+    /* Get the video overlay window */
+    case VIDIOCGWIN:
+    {
+        struct video_window vw;
 
-		vw.x = 0;
-		vw.y = 0;
-		vw.width = loops[nr]->width;
-		vw.height = loops[nr]->height;
-		vw.chromakey = 0;
-		vw.flags = 0;
-		vw.clipcount = 0;
+        vw.x = 0;
+        vw.y = 0;
+        vw.width = loops[nr]->width;
+        vw.height = loops[nr]->height;
+        vw.chromakey = 0;
+        vw.flags = 0;
+        vw.clipcount = 0;
 
-		if (copy_to_user((void*)arg, &vw, sizeof(vw)))
-			return -EFAULT;
-
-		return 0;
-	}
-	/* Set the video overlay window - passes clip list for hardware smarts , chromakey etc */
-	case VIDIOCSWIN:
-	{
-		struct video_window vw;
-			
-		if (copy_from_user(&vw, (void*)arg, sizeof(vw)))
-			return -EFAULT;
+        if (copy_to_user((void*)arg, &vw, sizeof(vw)))
+            return -EFAULT;
 
-		if (vw.flags)
-			return -EINVAL;
-
-		if (vw.clipcount)
-			return -EINVAL;
-
-		if (loops[nr]->height == vw.height &&
-		    loops[nr]->width == vw.width)
-			return 0;
+        return 0;
+    }
+    /* Set the video overlay window - passes clip list for hardware smarts , chromakey etc */
+    case VIDIOCSWIN:
+    {
+        struct video_window vw;
+            
+        if (copy_from_user(&vw, (void*)arg, sizeof(vw)))
+            return -EFAULT;
 
-		if (!ptr->in) {
-			return -EINVAL;
-		} else {
-			loops[nr]->height = vw.height;
-			loops[nr]->width = vw.width;
-			/* Make sure nobody is using the buffer while we
-			   fool around with it.
-			   We are also not allowing changes while
-			   somebody using mmap has the output open.
-			 */
-			down(&loops[nr]->lock);
-			if (loops[nr]->ropen) {
-				info("Can't change size while opened for read");
-				up(&loops[nr]->lock);
-				return -EINVAL;
-			}
+        if (vw.flags)
+            return -EINVAL;
 
-			if (loops[nr]->buffer)
-				rvfree(loops[nr]->buffer, loops[nr]->buflength * N_BUFFS);
+        if (vw.clipcount)
+            return -EINVAL;
+
+        if (loops[nr]->height == vw.height &&
+            loops[nr]->width == vw.width)
+            return 0;
 
-			loops[nr]->buflength = vw.width * vw.height * 4;
-			loops[nr]->buffer = rvmalloc(loops[nr]->buflength * N_BUFFS);
-			up(&loops[nr]->lock);
-		}
-		return 0;
-	}
-	/* Memory map buffer info */
-	case VIDIOCGMBUF:
-	{
-		struct video_mbuf vm;
-			
-		vm.size = loops[nr]->buflength * N_BUFFS;
-		vm.frames = N_BUFFS;
-		for (i = 0; i < vm.frames; i++)
-			vm.offsets[i] = i * loops[nr]->buflength;
+        if (!ptr->in) {
+            return -EINVAL;
+        } else {
+            loops[nr]->height = vw.height;
+            loops[nr]->width = vw.width;
+            /* Make sure nobody is using the buffer while we
+               fool around with it.
+               We are also not allowing changes while
+               somebody using mmap has the output open.
+             */
+            down(&loops[nr]->lock);
+            if (loops[nr]->ropen) {
+                info("Can't change size while opened for read");
+                up(&loops[nr]->lock);
+                return -EINVAL;
+            }
 
-		if (copy_to_user((void*)arg, &vm, sizeof(vm)))
-			return -EFAULT;
-
-		return 0;
-	}
-	/* Grab frames */
-	case VIDIOCMCAPTURE:
-	{
-		struct video_mmap vm;
-
-		if (ptr->in)
-			return -EINVAL;
+            if (loops[nr]->buffer)
+                rvfree(loops[nr]->buffer, loops[nr]->buflength * num_buffers);
 
-		if (!loops[nr]->buffer)
-			return -EINVAL;
-
-		if (copy_from_user(&vm, (void*)arg, sizeof(vm)))
-			return -EFAULT;
-
-		if (vm.format != loops[nr]->palette)
-			return -EINVAL;
-
-		if (vm.frame > N_BUFFS)
-			return -EINVAL;
+            loops[nr]->buflength = vw.width * vw.height * 4;
+            loops[nr]->buffer = rvmalloc(loops[nr]->buflength * num_buffers);
+            up(&loops[nr]->lock);
+        }
+        return 0;
+    }
+    /* Memory map buffer info */
+    case VIDIOCGMBUF:
+    {
+        struct video_mbuf vm;
+            
+        vm.size = loops[nr]->buflength * num_buffers;
+        vm.frames = num_buffers;
+        for (i = 0; i < vm.frames; i++)
+            vm.offsets[i] = i * loops[nr]->buflength;
 
-		return 0;
-	}
-	/* Sync with mmap grabbing */
-	case VIDIOCSYNC:
-	{
-		int frame;
-		unsigned long fw;
-
-		if (copy_from_user((void *)&frame, (void*)arg, sizeof(int)))
-			return -EFAULT;
+        if (copy_to_user((void*)arg, &vm, sizeof(vm)))
+            return -EFAULT;
 
-		if (ptr->in)
-			return -EINVAL;
+        return 0;
+    }
+    /* Grab frames */
+    case VIDIOCMCAPTURE:
+    {
+        struct video_mmap vm;
 
-		if (!loops[nr]->buffer)
-			return -EINVAL;
+        if (ptr->in)
+            return -EINVAL;
 
-		/* Ok, everything should be alright since the program
-		   should have called VIDIOMCAPTURE and we are ready to
-		   do the 'capturing' */
-		if (frame > 1)
+        if (!loops[nr]->buffer)
             return -EINVAL;
 
-		loops[nr]->frame = frame;
-#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)
-		fw = loops[nr]->frameswrite;
-		wait_event_interruptible(loops[nr]->wait, fw != loops[nr]->frameswrite);
-#else
-		interruptible_sleep_on(&loops[nr]->wait);
-#endif			
-		if (!loops[nr]->buffer)		/* possibly released during sleep */
-			return -EINVAL;
+        if (copy_from_user(&vm, (void*)arg, sizeof(vm)))
+            return -EFAULT;
+
+        if (vm.format != loops[nr]->palette)
+            return -EINVAL;
+
+        if (vm.frame > num_buffers)
+            return -EINVAL;
 
-		loops[nr]->framesread++;
+        return 0;
+    }
+    /* Sync with mmap grabbing */
+    case VIDIOCSYNC:
+    {
+        int frame;
+        unsigned long fw;
+
+        if (copy_from_user((void *)&frame, (void*)arg, sizeof(int)))
+            return -EFAULT;
 
-		return 0;
-	}
-	/* Get attached units */
-	case VIDIOCGUNIT:
-	{
-		struct video_unit vu;
-			
-		if (ptr->in)
-			vu.video = loops[nr]->vloopout->minor;
-		else
-			vu.video = loops[nr]->vloopin->minor;
+        if (ptr->in)
+            return -EINVAL;
+
+        if (!loops[nr]->buffer)
+            return -EINVAL;
+
+        /* Ok, everything should be alright since the program
+           should have called VIDIOMCAPTURE and we are ready to
+           do the 'capturing' */
+        //if (frame > 1)
+        if (frame > num_buffers-1)
+            return -EINVAL;
+
+        loops[nr]->frame = frame;
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)
+        fw = loops[nr]->frameswrite;
+        wait_event_interruptible(loops[nr]->wait, fw != loops[nr]->frameswrite);
+#else
+        interruptible_sleep_on(&loops[nr]->wait);
+#endif            
+        if (!loops[nr]->buffer)        /* possibly released during sleep */
+            return -EINVAL;
+
+        loops[nr]->framesread++;
 
-		vu.vbi = VIDEO_NO_UNIT;
-		vu.radio = VIDEO_NO_UNIT;
-		vu.audio = VIDEO_NO_UNIT;
-		vu.teletext = VIDEO_NO_UNIT;
+        return 0;
+    }
+    /* Get attached units */
+    case VIDIOCGUNIT:
+    {
+        struct video_unit vu;
+            
+        if (ptr->in)
+            vu.video = loops[nr]->vloopout->minor;
+        else
+            vu.video = loops[nr]->vloopin->minor;
 
-		if (copy_to_user((void*)arg, &vu, sizeof(vu)))
-			return -EFAULT;
+        vu.vbi = VIDEO_NO_UNIT;
+        vu.radio = VIDEO_NO_UNIT;
+        vu.audio = VIDEO_NO_UNIT;
+        vu.teletext = VIDEO_NO_UNIT;
 
-		return 0;
-	}
-	/* Get frame buffer */
-	case VIDIOCGFBUF:
-	{
-		struct video_buffer vb;
+        if (copy_to_user((void*)arg, &vu, sizeof(vu)))
+            return -EFAULT;
 
-		memset(&vb, 0, sizeof(vb));
-		vb.base = NULL;
+        return 0;
+    }
+    /* Get frame buffer */
+    case VIDIOCGFBUF:
+    {
+        struct video_buffer vb;
 
-		if (copy_to_user((void *)arg, (void *)&vb, sizeof(vb)))
-			return -EFAULT;
+        memset(&vb, 0, sizeof(vb));
+        vb.base = NULL;
 
-		return 0;
-	}
-	/* Start, end capture */
-	case VIDIOCCAPTURE:
-	{
-		int start;
+        if (copy_to_user((void *)arg, (void *)&vb, sizeof(vb)))
+            return -EFAULT;
 
-		if (copy_from_user(&start, (void*)arg, sizeof(int)))
-			return -EFAULT;
+        return 0;
+    }
+    /* Start, end capture */
+    case VIDIOCCAPTURE:
+    {
+        int start;
 
-		if (start) { 
+        if (copy_from_user(&start, (void*)arg, sizeof(int)))
+            return -EFAULT;
+
+        if (start) { 
             info ("Video loopback %d Capture started", nr);
         } else {
             info ("Video loopback %d Capture stopped", nr);
         }
 
-		return 0;
-	}
-	case VIDIOCGFREQ:
-	case VIDIOCSFREQ:
-	case VIDIOCGAUDIO:
-	case VIDIOCSAUDIO:
-		return -EINVAL;
-	case VIDIOCKEY:
-		return 0;
-	default:
-		return -ENOTTY;
-		//return -ENOIOCTLCMD;
-	}
-	return 0;
+        return 0;
+    }
+    case VIDIOCGFREQ:
+    case VIDIOCSFREQ:
+    case VIDIOCGAUDIO:
+    case VIDIOCSAUDIO:
+        return -EINVAL;
+    case VIDIOCKEY:
+        return 0;
+    default:
+        return -ENOTTY;
+        //return -ENOIOCTLCMD;
+    }
+    return 0;
 }
 
 static unsigned int vloopback_poll(struct file *f, struct poll_table_struct *wait)
 {
-	struct video_device *loopdev = video_devdata(f);
-	priv_ptr ptr = (priv_ptr)loopdev->priv;
-	int nr = ptr->pipenr;
+    struct video_device *loopdev = video_devdata(f);
+    priv_ptr ptr = (priv_ptr)loopdev->priv;
+    int nr = ptr->pipenr;
 
     if (debug > LOG_NODEBUG)
         info("Video loopback %d", nr);
 
-	if (loopdev == NULL)
-		return -EFAULT;
+    if (loopdev == NULL)
+        return -EFAULT;
 
-	if (!ptr->in)
-		return 0;
+    if (!ptr->in)
+        return 0;
 
-	if (loops[nr]->ioctlnr != -1) {
-		if (loops[nr]->zerocopy) {
-			return (POLLIN | POLLPRI | POLLOUT | POLLRDNORM);
-		} else {
-			return (POLLOUT);
-		}
-	}
-	return 0;
+    if (loops[nr]->ioctlnr != -1) {
+        if (loops[nr]->zerocopy) {
+            return (POLLIN | POLLPRI | POLLOUT | POLLRDNORM);
+        } else {
+            return (POLLOUT);
+        }
+    }
+    return 0;
 }
 
 static struct file_operations fileops_template =
 {
-	owner:		THIS_MODULE,
-	open:		vloopback_open,
-	release:	vloopback_release,
-	read:		vloopback_read,
-	write:		vloopback_write,
-	poll:		vloopback_poll,
-	ioctl:		vloopback_ioctl,
-	mmap:		vloopback_mmap,
+    owner:        THIS_MODULE,
+    open:        vloopback_open,
+    release:    vloopback_release,
+    read:        vloopback_read,
+    write:        vloopback_write,
+    poll:        vloopback_poll,
+    ioctl:        vloopback_ioctl,
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,15)
+    compat_ioctl:   v4l_compat_ioctl32,
+#endif
+    mmap:        vloopback_mmap,
 };
 
 static struct video_device vloopback_template =
@@ -1098,126 +1112,126 @@
     type:       VID_TYPE_CAPTURE,
 #endif
     minor:      -1,    
-	name:		"Video Loopback",
-	fops:		&fileops_template,
+    name:        "Video Loopback",
+    fops:        &fileops_template,
 #if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)
-	release:	video_device_release,
+    release:    video_device_release,
 #endif
 };
 
 static int create_pipe(int nr)
 {
-	int minor_in, minor_out , ret;
+    int minor_in, minor_out , ret;
 
     if (debug > LOG_NODEBUG)
         info("Video loopback %d", nr);
 
-	if (dev_offset == -1) {
-		minor_in  = minor_out = -1; /* autoassign */
+    if (dev_offset == -1) {
+        minor_in  = minor_out = -1; /* autoassign */
     } else {
-		minor_in  = 2 * nr + dev_offset;
-		minor_out = 2 * nr + 1 + dev_offset;
-	}
+        minor_in  = 2 * nr + dev_offset;
+        minor_out = 2 * nr + 1 + dev_offset;
+    }
 
-	/* allocate space for this pipe */
-	loops[nr]= kmalloc(sizeof(struct vloopback_pipe), GFP_KERNEL);
+    /* allocate space for this pipe */
+    loops[nr]= kmalloc(sizeof(struct vloopback_pipe), GFP_KERNEL);
 
-	if (!loops[nr])
-		return -ENOMEM;
-	/* set up a new video device plus our private area */
-	loops[nr]->vloopin = video_device_alloc();
+    if (!loops[nr])
+        return -ENOMEM;
+    /* set up a new video device plus our private area */
+    loops[nr]->vloopin = video_device_alloc();
 
-	if (loops[nr]->vloopin == NULL)
-		return -ENOMEM;
-	*loops[nr]->vloopin = vloopback_template;
-	loops[nr]->vloopin->priv = kmalloc(sizeof(struct vloopback_private),
-			                           GFP_KERNEL);
-	if (loops[nr]->vloopin->priv == NULL) {
-		kfree(loops[nr]->vloopin);
-		return -ENOMEM;
-	}
-	/* repeat for the output device */
-	loops[nr]->vloopout = video_device_alloc();
+    if (loops[nr]->vloopin == NULL)
+        return -ENOMEM;
+    *loops[nr]->vloopin = vloopback_template;
+    loops[nr]->vloopin->priv = kmalloc(sizeof(struct vloopback_private),
+                                       GFP_KERNEL);
+    if (loops[nr]->vloopin->priv == NULL) {
+        kfree(loops[nr]->vloopin);
+        return -ENOMEM;
+    }
+    /* repeat for the output device */
+    loops[nr]->vloopout = video_device_alloc();
 
-	if (loops[nr]->vloopout == NULL) {
-		kfree(loops[nr]->vloopin->priv);
-		kfree(loops[nr]->vloopin);
-		return -ENOMEM;
-	}
-	*loops[nr]->vloopout = vloopback_template;
-	loops[nr]->vloopout->priv = kmalloc(sizeof(struct vloopback_private),
-			                            GFP_KERNEL);
+    if (loops[nr]->vloopout == NULL) {
+        kfree(loops[nr]->vloopin->priv);
+        kfree(loops[nr]->vloopin);
+        return -ENOMEM;
+    }
+    *loops[nr]->vloopout = vloopback_template;
+    loops[nr]->vloopout->priv = kmalloc(sizeof(struct vloopback_private),
+                                        GFP_KERNEL);
 
-	if (loops[nr]->vloopout->priv == NULL) {
-		kfree(loops[nr]->vloopin->priv);
-		kfree(loops[nr]->vloopin);
-		kfree(loops[nr]->vloopout);
-		return -ENOMEM;
-	}
+    if (loops[nr]->vloopout->priv == NULL) {
+        kfree(loops[nr]->vloopin->priv);
+        kfree(loops[nr]->vloopin);
+        kfree(loops[nr]->vloopout);
+        return -ENOMEM;
+    }
 
-	((priv_ptr)loops[nr]->vloopin->priv)->pipenr = nr;
-	((priv_ptr)loops[nr]->vloopout->priv)->pipenr = nr;
-	loops[nr]->invalid_ioctl = 0; /* tibit */
-	loops[nr]->buffer = NULL;
-	loops[nr]->width = 0;
-	loops[nr]->height = 0;
-	loops[nr]->palette = 0;
-	loops[nr]->frameswrite = 0;
-	loops[nr]->framesread = 0;
-	loops[nr]->framesdumped = 0;
-	loops[nr]->wopen = 0;
-	loops[nr]->ropen = 0;
-	loops[nr]->frame = 0;
-	
-	((priv_ptr)loops[nr]->vloopin->priv)->in = 1;
-	((priv_ptr)loops[nr]->vloopout->priv)->in = 0;
+    ((priv_ptr)loops[nr]->vloopin->priv)->pipenr = nr;
+    ((priv_ptr)loops[nr]->vloopout->priv)->pipenr = nr;
+    loops[nr]->invalid_ioctl = 0; /* tibit */
+    loops[nr]->buffer = NULL;
+    loops[nr]->width = 0;
+    loops[nr]->height = 0;
+    loops[nr]->palette = 0;
+    loops[nr]->frameswrite = 0;
+    loops[nr]->framesread = 0;
+    loops[nr]->framesdumped = 0;
+    loops[nr]->wopen = 0;
+    loops[nr]->ropen = 0;
+    loops[nr]->frame = 0;
+    
+    ((priv_ptr)loops[nr]->vloopin->priv)->in = 1;
+    ((priv_ptr)loops[nr]->vloopout->priv)->in = 0;
     sprintf(loops[nr]->vloopin->name, "Video loopback %d input", nr);
     sprintf(loops[nr]->vloopout->name, "Video loopback %d output", nr);
 
 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,27)
-	loops[nr]->vloopin->type = 0;
-	loops[nr]->vloopout->type = VID_TYPE_CAPTURE;
+    loops[nr]->vloopin->type = 0;
+    loops[nr]->vloopout->type = VID_TYPE_CAPTURE;
 #endif
     loops[nr]->vloopout->minor = minor_out;
     loops[nr]->vloopin->minor = minor_in;
 
-	init_waitqueue_head(&loops[nr]->wait);
-	init_MUTEX(&loops[nr]->lock);
-	
-	ret = video_register_device(loops[nr]->vloopin, VFL_TYPE_GRABBER, minor_in);
-	
-	if ((ret == -1 ) || ( ret == -23 )) {
-		info("error registering device %s", loops[nr]->vloopin->name);
-		kfree(loops[nr]->vloopin->priv);
-		kfree(loops[nr]->vloopin);
-		kfree(loops[nr]->vloopout->priv);
-		kfree(loops[nr]->vloopout);
-		kfree(loops[nr]);
-		loops[nr] = NULL;
-		return ret;
-	}
-	
-	ret = video_register_device(loops[nr]->vloopout, VFL_TYPE_GRABBER, minor_out);
-	
-	if ((ret ==-1) || (ret == -23)) {
-		info("error registering device %s", loops[nr]->vloopout->name);
-		kfree(loops[nr]->vloopin->priv);
-		video_unregister_device(loops[nr]->vloopin);
-		kfree(loops[nr]->vloopout->priv);
-		kfree(loops[nr]->vloopout);
-		kfree(loops[nr]);
-		loops[nr] = NULL;
-		return ret;
-	}
-	
-	loops[nr]->ioctldata = kmalloc(1024, GFP_KERNEL);
-	loops[nr]->ioctlretdata = kmalloc(1024, GFP_KERNEL);
-	return 0;
+    init_waitqueue_head(&loops[nr]->wait);
+    init_MUTEX(&loops[nr]->lock);
+    
+    ret = video_register_device(loops[nr]->vloopin, VFL_TYPE_GRABBER, minor_in);
+    
+    if ((ret == -1 ) || ( ret == -23 )) {
+        info("error registering device %s", loops[nr]->vloopin->name);
+        kfree(loops[nr]->vloopin->priv);
+        kfree(loops[nr]->vloopin);
+        kfree(loops[nr]->vloopout->priv);
+        kfree(loops[nr]->vloopout);
+        kfree(loops[nr]);
+        loops[nr] = NULL;
+        return ret;
+    }
+    
+    ret = video_register_device(loops[nr]->vloopout, VFL_TYPE_GRABBER, minor_out);
+    
+    if ((ret ==-1) || (ret == -23)) {
+        info("error registering device %s", loops[nr]->vloopout->name);
+        kfree(loops[nr]->vloopin->priv);
+        video_unregister_device(loops[nr]->vloopin);
+        kfree(loops[nr]->vloopout->priv);
+        kfree(loops[nr]->vloopout);
+        kfree(loops[nr]);
+        loops[nr] = NULL;
+        return ret;
+    }
+    
+    loops[nr]->ioctldata = kmalloc(1024, GFP_KERNEL);
+    loops[nr]->ioctlretdata = kmalloc(1024, GFP_KERNEL);
+    return 0;
 }
 
 
 /****************************************************************************
- *	init stuff
+ *    init stuff
  ****************************************************************************/
 
 
@@ -1230,7 +1244,7 @@
 MODULE_PARM(pipes, "i");
 #endif
 
-MODULE_PARM_DESC(pipes, "Nr of pipes to create (each pipe uses two video devices)");
+MODULE_PARM_DESC(pipes, " Nr of pipes to create (each pipe uses two video devices)");
 
 #if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)
 module_param(spares, int, 000);
@@ -1238,7 +1252,16 @@
 MODULE_PARM(spares, "i");
 #endif
 
-MODULE_PARM_DESC(spares, "Nr of spare pipes that should be created");
+MODULE_PARM_DESC(spares, " Nr of spare pipes that should be created");
+
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)
+module_param(num_buffers, int, 000);
+#else
+MODULE_PARM(num_buffers, "i");
+#endif
+
+MODULE_PARM_DESC(num_buffers, " Prefered numbers of internal buffers to map (default 2)");
+
 
 #if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)
 module_param(dev_offset, int, 000);
@@ -1246,7 +1269,7 @@
 MODULE_PARM(dev_offset_param, "i");
 #endif
 
-MODULE_PARM_DESC(dev_offset, "Prefered offset for video device numbers");
+MODULE_PARM_DESC(dev_offset, " Prefered offset for video device numbers");
 
 
 #if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)
@@ -1255,62 +1278,68 @@
 MODULE_PARM(debug_param, "i");
 #endif
 
-MODULE_PARM_DESC(debug, "Enable module debug level 0-3 (by default 0)");
+MODULE_PARM_DESC(debug, " Enable module debug level 0-3 (by default 0)");
 
 MODULE_LICENSE("GPL");
 MODULE_VERSION( VLOOPBACK_VERSION );
 
 static int __init vloopback_init(void)
 {
-	int i,ret;
+    int i, ret;
 
-	info("video4linux loopback driver v"VLOOPBACK_VERSION);
+    info("video4linux loopback driver v"VLOOPBACK_VERSION);
 
-	if (pipes == -1) 
+    if (pipes == -1) 
         pipes = 1;
 
-	if (pipes > MAX_PIPES) {
-		pipes = MAX_PIPES;
-		info("Nr of pipes is limited to: %d", MAX_PIPES);
-	}
+    if (pipes > MAX_PIPES) {
+        pipes = MAX_PIPES;
+        info("Nr of pipes is limited to: %d", MAX_PIPES);
+    }
 
-	for (i = 0; i < pipes; i++) {
-		
-		ret = create_pipe(i);
+    if (num_buffers < N_BUFFS) {
+        num_buffers = N_BUFFS;
+        info("Nr of buffer set to default value %d", N_BUFFS);
+    }
 
-		if (ret == 0) {
-			info("Loopback %d registered, input: video%d,"
-			     " output: video%d",
-			     i, loops[i]->vloopin->minor,
-			     loops[i]->vloopout->minor);
-			nr_o_pipes = i + 1;
-		} else {
-			return ret;
-		}
-	}
-	return 0;
+    for (i = 0; i < pipes; i++) {
+        
+        ret = create_pipe(i);
+
+        if (ret == 0) {
+            info("Loopback %d registered, input: video%d,"
+                 " output: video%d",
+                 i, loops[i]->vloopin->minor,
+                 loops[i]->vloopout->minor);
+            info("Loopback %d , Using %d buffers", i, num_buffers);
+            nr_o_pipes = i + 1;
+        } else {
+            return ret;
+        }
+    }
+    return 0;
 }
 
 static void __exit cleanup_vloopback_module(void)
 {
-	int i;
+    int i;
 
-	info("Unregistering video4linux loopback devices");
+    info("Unregistering video4linux loopback devices");
 
     for (i = 0; i < nr_o_pipes; i++) {
         if (loops[i]) {
-		    kfree(loops[i]->vloopin->priv);
-		    video_unregister_device(loops[i]->vloopin);
-		    kfree(loops[i]->vloopout->priv);
-		    video_unregister_device(loops[i]->vloopout);
-		    
+            kfree(loops[i]->vloopin->priv);
+            video_unregister_device(loops[i]->vloopin);
+            kfree(loops[i]->vloopout->priv);
+            video_unregister_device(loops[i]->vloopout);
+            
             if (loops[i]->buffer) 
-                rvfree(loops[i]->buffer, loops[i]->buflength * N_BUFFS);
+                rvfree(loops[i]->buffer, loops[i]->buflength * num_buffers);
 
-		    kfree(loops[i]->ioctldata);
-		    kfree(loops[i]->ioctlretdata);
-		    kfree(loops[i]);
-	    }
+            kfree(loops[i]->ioctldata);
+            kfree(loops[i]->ioctlretdata);
+            kfree(loops[i]);
+        }
     }        
 }