comparison vloopback.c @ 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 bce647a9dd4b
comparison
equal deleted inserted replaced
7:2fce9e157b8d 8:80590d10a596
1 /* 1 /*
2 * vloopback.c 2 * vloopback.c
3 * 3 *
4 * Copyright Jeroen Vreeken (pe1rxq@amsat.org), 2000 4 * Copyright Jeroen Vreeken (pe1rxq@amsat.org), 2000
5 * Additional copyright by the contributing authors in the 5 * Additional copyright by the contributing authors in the
6 * change history below, 2000-2007 6 * change history below, 2000-2007
7 * 7 *
8 * Published under the GNU Public License. 8 * Published under the GNU Public License.
9 * 9 *
10 * The Video loopback Loopback Device is no longer systematically maintained. 10 * The Video loopback Loopback Device is no longer systematically maintained.
11 * The project is a secondary project for the project "motion" found at 11 * The project is a secondary project for the project "motion" found at
12 * http://motion.sourceforge.net/ and 12 * http://motion.sourceforge.net/ and
13 * http://www.lavrsen.dk/twiki/bin/view/Motion/WebHome 13 * http://www.lavrsen.dk/twiki/bin/view/Motion/WebHome
14 * and with the vloopback stored at 14 * and with the vloopback stored at
15 * http://www.lavrsen.dk/twiki/bin/view/Motion/Video loopbackFourLinuxLoopbackDevice 15 * http://www.lavrsen.dk/twiki/bin/view/Motion/Video loopbackFourLinuxLoopbackDevice
16 * 16 *
17 * CHANGE HISTORY 17 * CHANGE HISTORY
18 * 18 *
19 * UPDATED: Jeroen Vreeken. 19 * UPDATED: Jeroen Vreeken.
20 * Added locks for smp machines. UNTESTED! 20 * Added locks for smp machines. UNTESTED!
21 * Made the driver much more cpu friendly by using 21 * Made the driver much more cpu friendly by using
22 * a wait queue. 22 * a wait queue.
23 * Went from vmalloc to rvmalloc (yes, I stole the code 23 * Went from vmalloc to rvmalloc (yes, I stole the code
24 * like everybody else) and implemented mmap. 24 * like everybody else) and implemented mmap.
25 * Implemented VIDIOCGUNIT and removed size/palette checks 25 * Implemented VIDIOCGUNIT and removed size/palette checks
26 * in VIDIOCSYNC. 26 * in VIDIOCSYNC.
27 * Cleaned up a lot of code. 27 * Cleaned up a lot of code.
28 * Changed locks to semaphores. 28 * Changed locks to semaphores.
29 * Disabled changing size while somebody is using mmap 29 * Disabled changing size while somebody is using mmap
30 * Changed mapped check to open check, also don't allow 30 * Changed mapped check to open check, also don't allow
31 * a open for write while somebody is reading. 31 * a open for write while somebody is reading.
32 * Added /proc support 32 * Added /proc support
33 * Set dumped count to zero at open. 33 * Set dumped count to zero at open.
34 * Modified /proc layout (added vloopbacks entry) 34 * Modified /proc layout (added vloopbacks entry)
35 * 35 *
36 * 05.10.00 (MTS) Added Linux 2.2 support 36 * 05.10.00 (MTS) Added Linux 2.2 support
37 * 06.10.00 (J Vreeken) Fixed 2.2 support to make things work under 2.4 again. 37 * 06.10.00 (J Vreeken) Fixed 2.2 support to make things work under 2.4 again.
38 * 17.10.00 (J Vreeken) Added zero copy mode 38 * 17.10.00 (J Vreeken) Added zero copy mode
39 * 19.10.00 (J Vreeken) Added SIGIO on device close. 39 * 19.10.00 (J Vreeken) Added SIGIO on device close.
40 * 24.10.00 (J Vreeken) Modified 2.2 stuff and removed spinlock.h 40 * 24.10.00 (J Vreeken) Modified 2.2 stuff and removed spinlock.h
41 * released 0.81 41 * released 0.81
42 * 27.10.00 (J Vreeken) Implemented poll 42 * 27.10.00 (J Vreeken) Implemented poll
43 * released 0.82 43 * released 0.82
44 * 17.01.01 (J Vreeken) support for xawtv 44 * 17.01.01 (J Vreeken) support for xawtv
45 * Implemented VIDIOCGFBUF 45 * Implemented VIDIOCGFBUF
46 * Additional checks on framebuffer freeing. 46 * Additional checks on framebuffer freeing.
47 * released 0.83 47 * released 0.83
48 * 31.01.01 (J Vreeken) Removed need for 'struct ioctl', use _IOC_SIZE() and 48 * 31.01.01 (J Vreeken) Removed need for 'struct ioctl', use _IOC_SIZE() and
49 * IOC_IN instead. 49 * IOC_IN instead.
50 * Change the ioctlnr passing to 'unsigned long int' 50 * Change the ioctlnr passing to 'unsigned long int'
51 * Instead of just one byte. 51 * Instead of just one byte.
52 * THIS BREAKS COMPATIBILITY WITH PREVIOUS VERSIONS!!! 52 * THIS BREAKS COMPATIBILITY WITH PREVIOUS VERSIONS!!!
53 * 29.06.01 (J Vreeken) Added dev_offset module option 53 * 29.06.01 (J Vreeken) Added dev_offset module option
54 * Made vloopback_template sane 54 * Made vloopback_template sane
55 * Added double buffering support 55 * Added double buffering support
56 * Made vloopback less verbose 56 * Made vloopback less verbose
57 * 20.11.01 (tibit) Made dev_offset option sane 57 * 20.11.01 (tibit) Made dev_offset option sane
58 * "Fixed" zerocopy mode by defining the ioctl 58 * "Fixed" zerocopy mode by defining the ioctl
59 * VIDIOCSINVALID. An application which provides data 59 * VIDIOCSINVALID. An application which provides data
60 * has to issue it when it encounters an error in 60 * has to issue it when it encounters an error in
61 * ioctl processing. See dummy.c for examples. 61 * ioctl processing. See dummy.c for examples.
62 * 26.11.03 (Kenneth Lavrsen) 62 * 26.11.03 (Kenneth Lavrsen)
63 * released 0.91 63 * released 0.91
64 * 0.91 is the combination of the 0.90-tibit by 64 * 0.91 is the combination of the 0.90-tibit by
65 * Tilmann Bitterberg and an update of the Makefile by 65 * Tilmann Bitterberg and an update of the Makefile by
66 * Roberto Carvajal. 66 * Roberto Carvajal.
67 * 23.01.05 (W Brack) 67 * 23.01.05 (W Brack)
68 * (don't know what happened to the comments for 0.92 68 * (don't know what happened to the comments for 0.92
69 * and 0.93, but I tentatively named this one as 0.99) 69 * and 0.93, but I tentatively named this one as 0.99)
70 * enhanced for linux-2.6, with #ifdef to keep it 70 * enhanced for linux-2.6, with #ifdef to keep it
71 * compatible with linux-2.4. For linux versions 71 * compatible with linux-2.4. For linux versions
72 * > 2.5, I changed the memory management 72 * > 2.5, I changed the memory management
73 * routines to the "more modern" way, most of it 73 * routines to the "more modern" way, most of it
74 * shamelessly copied from other drivers. I also 74 * shamelessly copied from other drivers. I also
75 * added in the code necessary to avoid the "videodev 75 * added in the code necessary to avoid the "videodev
76 * has no release callback" message when installing. 76 * has no release callback" message when installing.
77 * For versions < 2.5, I updated the routines to be 77 * For versions < 2.5, I updated the routines to be
78 * closer to several other drivers. 78 * closer to several other drivers.
79 * 79 *
80 * 04.02.05 (Angel Carpintero) 80 * 04.02.05 (Angel Carpintero)
81 * Fixed version number to 0.93-pre1. 81 * Fixed version number to 0.93-pre1.
82 * Fixed warning for interruptible_sleep_on() deprecated and added 82 * Fixed warning for interruptible_sleep_on() deprecated and added
83 * wait_event_interruptible compatible with 2.6.x and 2.7. 83 * wait_event_interruptible compatible with 2.6.x and 2.7.
84 * Fixed memory manager for kernel version > 2.6.9. 84 * Fixed memory manager for kernel version > 2.6.9.
85 * 85 *
86 * 07.02.05 (Kenneth Lavrsen) 86 * 07.02.05 (Kenneth Lavrsen)
87 * Changed version to 0.94. 87 * Changed version to 0.94.
88 * Released as formal released version 88 * Released as formal released version
89 * 89 *
90 * 20.02.05 (W Brack) 90 * 20.02.05 (W Brack)
91 * Fixed error with wait_event_interruptible. 91 * Fixed error with wait_event_interruptible.
92 * Fixed crash when pipe source was stopped before dest. 92 * Fixed crash when pipe source was stopped before dest.
93 * 93 *
94 * 20.02.05 (Angel Carpintero) 94 * 20.02.05 (Angel Carpintero)
95 * Added install and uninstall in Makefile. 95 * Added install and uninstall in Makefile.
96 * 96 *
97 * 97 *
98 * 25.04.05 (Angel Carpintero) 98 * 25.04.05 (Angel Carpintero)
99 * Included Samuel Audet's patch, it checks if the input is already 99 * Included Samuel Audet's patch, it checks if the input is already
100 * opened in write mode. 100 * opened in write mode.
101 * 101 *
102 * 02.05.05 (Kenneth Lavrsen) 102 * 02.05.05 (Kenneth Lavrsen)
103 * Released 0.95-snap2 formerly as 0.95 103 * Released 0.95-snap2 formerly as 0.95
104 * 104 *
105 * 10.05.05 (Angel Carpintero) 105 * 10.05.05 (Angel Carpintero)
106 * Added MODULE_VERSION(), fixed create_pipes when video_register_device() returns 106 * Added MODULE_VERSION(), fixed create_pipes when video_register_device() returns
107 * -ENFILE . 107 * -ENFILE .
108 * Fix warnings about checking return value from copy_to_user() and copy_from_user() functions. 108 * Fix warnings about checking return value from copy_to_user() and copy_from_user() functions.
109 * 109 *
110 * 14.11.05 (Angel Carpintero) 110 * 14.11.05 (Angel Carpintero)
111 * Added <linux/version.h> that includes LINUX_VERSION_CODE and KERNEL_VERSION to fix 111 * Added <linux/version.h> that includes LINUX_VERSION_CODE and KERNEL_VERSION to fix
112 * compilation agains kernel 2.6.14 , change version to 0.97-snap1 112 * compilation agains kernel 2.6.14 , change version to 0.97-snap1
113 * 113 *
114 * 19.12.05 (Angel Carpintero) 114 * 19.12.05 (Angel Carpintero)
115 * Added to example option to choose between rgb24 or yuv420p palettes. 115 * Added to example option to choose between rgb24 or yuv420p palettes.
116 * 116 *
117 * 31.12.05 (Angel Carpintero) 117 * 31.12.05 (Angel Carpintero)
118 * Fixed examples, remove perror calls and add support to dummy.c for sysfs. 118 * Fixed examples, remove perror calls and add support to dummy.c for sysfs.
119 * 119 *
120 * 04.06.06 (Angel Carpintero) 120 * 04.06.06 (Angel Carpintero)
121 * Add module_param() for kernel > 2.5 because MODULE_PARAM() macro is obsolete. 121 * Add module_param() for kernel > 2.5 because MODULE_PARAM() macro is obsolete.
122 * 122 *
123 * 17.06.06 (Angel Carpintero) 123 * 17.06.06 (Angel Carpintero)
124 * Release version 1.0 with some fixes and code clean up. Added a Jack Bates contribution 124 * Release version 1.0 with some fixes and code clean up. Added a Jack Bates contribution
125 * to allow build a kernel module in debian way. 125 * to allow build a kernel module in debian way.
126 * 126 *
127 * 26.06.06 (Angel Carpintero) 127 * 26.06.06 (Angel Carpintero)
128 * Added some improvements in Makefile. Fix a problem to compile in Suse. 128 * Added some improvements in Makefile. Fix a problem to compile in Suse.
129 * 129 *
130 * 130 *
131 * 02.11.06 (Angel Carpintero) 131 * 02.11.06 (Angel Carpintero)
132 * Make compatible with new kernel stable version 2.6.18, Many functions and declarations has 132 * Make compatible with new kernel stable version 2.6.18, Many functions and declarations has
133 * been moved to media/v42l-dev.h and remove from videodev.h/videodev2.h 133 * been moved to media/v42l-dev.h and remove from videodev.h/videodev2.h
134 * 134 *
135 * 18.01.07 (Angel Carpintero) 135 * 18.01.07 (Angel Carpintero)
136 * Change -ENOIOCTLCMD by more appropiate error -ENOTTY. 136 * Change -ENOIOCTLCMD by more appropiate error -ENOTTY.
137 * 137 *
138 * 18.05.08 (Angel Carpintero) 138 * 18.05.08 (Angel Carpintero)
139 * Release 1.1-rc1 as 1.1 stable working with 2.6.24 139 * Release 1.1-rc1 as 1.1 stable working with 2.6.24
140 * 140 *
141 * 17.08.08 (Angel Carpintero) 141 * 17.08.08 (Angel Carpintero)
142 * kill_proc() deprecated ,pid API changed , type and owner not available in 142 * kill_proc() deprecated ,pid API changed , type and owner not available in
143 * video_device struct, added param debug. 143 * video_device struct, added param debug.
144 *
145 * 24.08.08 (Angel Carpintero)
146 * Added compat_iotcl32 init in fopsl, replace tabs by 4 spaces in source code,
147 * add number of buffers as module param.
144 */ 148 */
145 149
146 150
147 #define VLOOPBACK_VERSION "1.2-trunk" 151 #define VLOOPBACK_VERSION "1.2-trunk"
148 152
149 /* Include files common to 2.4 and 2.6 versions */ 153 /* Include files common to 2.4 and 2.6 versions */
150 #include <linux/version.h> /* >= 2.6.14 LINUX_VERSION_CODE */ 154 #include <linux/version.h> /* >= 2.6.14 LINUX_VERSION_CODE */
151 #include <linux/errno.h> 155 #include <linux/errno.h>
152 #include <linux/kernel.h> 156 #include <linux/kernel.h>
153 #include <linux/module.h> 157 #include <linux/module.h>
154 #include <linux/pagemap.h> 158 #include <linux/pagemap.h>
155 159
165 #if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0) 169 #if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)
166 #include <asm/ioctl.h> 170 #include <asm/ioctl.h>
167 #include <asm/page.h> 171 #include <asm/page.h>
168 #include <asm/pgtable.h> 172 #include <asm/pgtable.h>
169 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,10) 173 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,10)
170 #ifndef remap_pfn_range 174 #ifndef remap_pfn_range
171 #define remap_pfn_range(a,b,c,d,e) \ 175 #define remap_pfn_range(a,b,c,d,e) \
172 remap_page_range((a),(b),(c)<<PAGE_SHIFT,(d),(e)) 176 remap_page_range((a),(b),(c)<<PAGE_SHIFT,(d),(e))
173 #endif 177 #endif
174 #ifndef vmalloc_to_pfn 178 #ifndef vmalloc_to_pfn
175 #define vmalloc_to_pfn(a) page_to_pfn(vmalloc_to_page((a))) 179 #define vmalloc_to_pfn(a) page_to_pfn(vmalloc_to_page((a)))
176 #endif 180 #endif
177 #endif 181 #endif
178 #include <asm/uaccess.h> 182 #include <asm/uaccess.h>
179 #include <linux/init.h> 183 #include <linux/init.h>
180 #include <linux/device.h> 184 #include <linux/device.h>
183 #include <linux/slab.h> 187 #include <linux/slab.h>
184 #include <linux/wrapper.h> 188 #include <linux/wrapper.h>
185 #include <asm/io.h> 189 #include <asm/io.h>
186 #endif 190 #endif
187 191
188 #define VIDIOCSINVALID _IO('v',BASE_VIDIOCPRIVATE+1) 192 #define VIDIOCSINVALID _IO('v',BASE_VIDIOCPRIVATE+1)
189 193
190 #define verbose(format, arg...) if (printk_ratelimit()) \ 194 #define verbose(format, arg...) if (printk_ratelimit()) \
191 printk(KERN_INFO "[%s] %s: " format "\n" "", \ 195 printk(KERN_INFO "[%s] %s: " format "\n" "", \
192 __FUNCTION__, __FILE__, ## arg) 196 __FUNCTION__, __FILE__, ## arg)
193 197
199 #define LOG_FUNCTIONS 1 203 #define LOG_FUNCTIONS 1
200 #define LOG_IOCTL 2 204 #define LOG_IOCTL 2
201 #define LOG_VERBOSE 3 205 #define LOG_VERBOSE 3
202 206
203 struct vloopback_private { 207 struct vloopback_private {
204 int pipenr; 208 int pipenr;
205 int in; /* bool , is being feed ? */ 209 int in; /* bool , is being feed ? */
206 }; 210 };
207 211
208 typedef struct vloopback_private *priv_ptr; 212 typedef struct vloopback_private *priv_ptr;
209 213
210 struct vloopback_pipe { 214 struct vloopback_pipe {
211 struct video_device *vloopin; 215 struct video_device *vloopin;
212 struct video_device *vloopout; 216 struct video_device *vloopout;
213 char *buffer; 217 char *buffer;
214 unsigned long buflength; 218 unsigned long buflength;
215 unsigned int width, height; 219 unsigned int width, height;
216 unsigned int palette; 220 unsigned int palette;
217 unsigned long frameswrite; 221 unsigned long frameswrite;
218 unsigned long framesread; 222 unsigned long framesread;
219 unsigned long framesdumped; 223 unsigned long framesdumped;
220 unsigned int wopen; 224 unsigned int wopen;
221 unsigned int ropen; 225 unsigned int ropen;
222 struct semaphore lock; 226 struct semaphore lock;
223 wait_queue_head_t wait; 227 wait_queue_head_t wait;
224 unsigned int frame; 228 unsigned int frame;
225 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,27) 229 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,27)
226 unsigned int pid; 230 unsigned int pid;
227 #else 231 #else
228 struct pid *pid; 232 struct pid *pid;
229 #endif 233 #endif
230 unsigned int zerocopy; 234 unsigned int zerocopy;
231 unsigned long int ioctlnr; 235 unsigned long int ioctlnr;
232 unsigned int invalid_ioctl; /* 0 .. none invalid; 1 .. invalid */ 236 unsigned int invalid_ioctl; /* 0 .. none invalid; 1 .. invalid */
233 unsigned int ioctllength; 237 unsigned int ioctllength;
234 char *ioctldata; 238 char *ioctldata;
235 char *ioctlretdata; 239 char *ioctlretdata;
236 }; 240 };
237 241
238 #define MAX_PIPES 16 242 #define MAX_PIPES 16
239 #define N_BUFFS 2 /* Number of buffers used for pipes */ 243 #define N_BUFFS 2 /* Number of buffers used for pipes */
240 244
241 static struct vloopback_pipe *loops[MAX_PIPES]; 245 static struct vloopback_pipe *loops[MAX_PIPES];
242 static int nr_o_pipes = 0; 246 static int nr_o_pipes = 0;
243 static int pipes = -1; 247 static int pipes = -1;
244 static int spares = 0; 248 static int spares = 0;
249 static unsigned int num_buffers = N_BUFFS;
245 static int pipesused = 0; 250 static int pipesused = 0;
246 static int dev_offset = -1; 251 static int dev_offset = -1;
247 static unsigned int debug = LOG_NODEBUG; 252 static unsigned int debug = LOG_NODEBUG;
248 253
249 /********************************************************************** 254 /**********************************************************************
258 */ 263 */
259 static inline unsigned long kvirt_to_pa(unsigned long adr) 264 static inline unsigned long kvirt_to_pa(unsigned long adr)
260 { 265 {
261 unsigned long kva; 266 unsigned long kva;
262 267
263 kva = (unsigned long)page_address(vmalloc_to_page((void *)adr)); 268 kva = (unsigned long)page_address(vmalloc_to_page((void *)adr));
264 kva |= adr & (PAGE_SIZE-1); /* restore the offset */ 269 kva |= adr & (PAGE_SIZE-1); /* restore the offset */
265 return __pa(kva); 270 return __pa(kva);
266 } 271 }
267 #endif 272 #endif
268 273
269 static void *rvmalloc(unsigned long size) 274 static void *rvmalloc(unsigned long size)
270 { 275 {
271 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) 276 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
272 struct page *page; 277 struct page *page;
273 #endif 278 #endif
274 void *mem; 279 void *mem;
275 unsigned long adr; 280 unsigned long adr;
276 281
277 size = PAGE_ALIGN(size); 282 size = PAGE_ALIGN(size);
278 mem = vmalloc_32(size); 283 mem = vmalloc_32(size);
279 if (!mem) 284 if (!mem)
280 return NULL; 285 return NULL;
281 memset(mem, 0, size); /* Clear the ram out, no junk to the user */ 286 memset(mem, 0, size); /* Clear the ram out, no junk to the user */
282 adr = (unsigned long) mem; 287 adr = (unsigned long) mem;
283 while (size > 0) { 288 while (size > 0) {
284 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) 289 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
285 page = vmalloc_to_page((void *)adr); 290 page = vmalloc_to_page((void *)adr);
286 mem_map_reserve(page); 291 mem_map_reserve(page);
287 #else 292 #else
288 SetPageReserved(vmalloc_to_page((void *)adr)); 293 SetPageReserved(vmalloc_to_page((void *)adr));
289 #endif 294 #endif
290 adr += PAGE_SIZE; 295 adr += PAGE_SIZE;
291 size -= PAGE_SIZE; 296 size -= PAGE_SIZE;
292 } 297 }
293 298
294 return mem; 299 return mem;
295 } 300 }
296 301
297 static void rvfree(void *mem, unsigned long size) 302 static void rvfree(void *mem, unsigned long size)
298 { 303 {
299 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) 304 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
300 struct page *page; 305 struct page *page;
301 #endif 306 #endif
302 unsigned long adr; 307 unsigned long adr;
303 308
304 if (!mem) 309 if (!mem)
305 return; 310 return;
306 311
307 adr = (unsigned long) mem; 312 adr = (unsigned long) mem;
308 while ((long) size > 0) { 313 while ((long) size > 0) {
309 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) 314 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
310 page = vmalloc_to_page((void *)adr); 315 page = vmalloc_to_page((void *)adr);
311 mem_map_unreserve(page); 316 mem_map_unreserve(page);
312 #else 317 #else
313 ClearPageReserved(vmalloc_to_page((void *)adr)); 318 ClearPageReserved(vmalloc_to_page((void *)adr));
314 #endif 319 #endif
315 adr += PAGE_SIZE; 320 adr += PAGE_SIZE;
316 size -= PAGE_SIZE; 321 size -= PAGE_SIZE;
317 } 322 }
318 vfree(mem); 323 vfree(mem);
319 } 324 }
320 325
321 326
322 static int create_pipe(int nr); 327 static int create_pipe(int nr);
323 328
324 static int fake_ioctl(int nr, unsigned long int cmd, void *arg) 329 static int fake_ioctl(int nr, unsigned long int cmd, void *arg)
325 { 330 {
326 unsigned long fw; 331 unsigned long fw;
327 332
328 if (debug > LOG_NODEBUG) 333 if (debug > LOG_NODEBUG)
329 info("Video loopback %d cmd %lu", nr, cmd); 334 info("Video loopback %d cmd %lu", nr, cmd);
330 335
331 loops[nr]->ioctlnr = cmd; 336 loops[nr]->ioctlnr = cmd;
332 memcpy(loops[nr]->ioctldata, arg, _IOC_SIZE(cmd)); 337 memcpy(loops[nr]->ioctldata, arg, _IOC_SIZE(cmd));
333 loops[nr]->ioctllength = _IOC_SIZE(cmd); 338 loops[nr]->ioctllength = _IOC_SIZE(cmd);
334 339
335 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,27) 340 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,27)
336 kill_proc(loops[nr]->pid, SIGIO, 1); /* Signal the pipe feeder */ 341 kill_proc(loops[nr]->pid, SIGIO, 1); /* Signal the pipe feeder */
337 #else 342 #else
338 kill_pid(loops[nr]->pid, SIGIO, 1); 343 kill_pid(loops[nr]->pid, SIGIO, 1);
339 #endif 344 #endif
340 345
341 #if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0) 346 #if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)
342 fw = loops[nr]->frameswrite; 347 fw = loops[nr]->frameswrite;
343 wait_event_interruptible(loops[nr]->wait, fw != loops[nr]->frameswrite); 348 wait_event_interruptible(loops[nr]->wait, fw != loops[nr]->frameswrite);
344 #else 349 #else
345 interruptible_sleep_on(&loops[nr]->wait); 350 interruptible_sleep_on(&loops[nr]->wait);
346 #endif 351 #endif
347 if (cmd & IOC_IN) { 352 if (cmd & IOC_IN) {
348 if (memcmp (arg, loops[nr]->ioctlretdata, _IOC_SIZE(cmd))) 353 if (memcmp (arg, loops[nr]->ioctlretdata, _IOC_SIZE(cmd)))
349 return 1; 354 return 1;
350 } else { 355 } else {
351 memcpy (arg, loops[nr]->ioctlretdata, _IOC_SIZE(cmd)); 356 memcpy (arg, loops[nr]->ioctlretdata, _IOC_SIZE(cmd));
352 } 357 }
353 return 0; 358 return 0;
354 } 359 }
355 360
356 static int vloopback_open(struct inode *inod, struct file *f) 361 static int vloopback_open(struct inode *inod, struct file *f)
357 { 362 {
358 struct video_device *loopdev = video_devdata(f); 363 struct video_device *loopdev = video_devdata(f);
359 priv_ptr ptr = (priv_ptr)loopdev->priv; 364 priv_ptr ptr = (priv_ptr)loopdev->priv;
360 int nr = ptr->pipenr; 365 int nr = ptr->pipenr;
361 366
362 if (debug > LOG_NODEBUG) 367 if (debug > LOG_NODEBUG)
363 info("Video loopback %d", nr); 368 info("Video loopback %d", nr);
364 369
365 /* Only allow a output to be opened if there is someone feeding 370 /* Only allow a output to be opened if there is someone feeding
366 * the pipe. 371 * the pipe.
367 */ 372 */
368 if (!ptr->in) { 373 if (!ptr->in) {
369 if (loops[nr]->buffer == NULL) 374 if (loops[nr]->buffer == NULL)
370 return -EINVAL; 375 return -EINVAL;
371 376
372 loops[nr]->framesread = 0; 377 loops[nr]->framesread = 0;
373 loops[nr]->ropen = 1; 378 loops[nr]->ropen = 1;
374 } else { 379 } else {
375 if (loops[nr]->ropen || loops[nr]->wopen) 380 if (loops[nr]->ropen || loops[nr]->wopen)
376 return -EBUSY; 381 return -EBUSY;
377 382
378 loops[nr]->framesdumped = 0; 383 loops[nr]->framesdumped = 0;
379 loops[nr]->frameswrite = 0; 384 loops[nr]->frameswrite = 0;
380 loops[nr]->wopen = 1; 385 loops[nr]->wopen = 1;
381 loops[nr]->zerocopy = 0; 386 loops[nr]->zerocopy = 0;
382 loops[nr]->ioctlnr = -1; 387 loops[nr]->ioctlnr = -1;
383 pipesused++; 388 pipesused++;
384 if (nr_o_pipes-pipesused<spares) { 389 if (nr_o_pipes-pipesused<spares) {
385 if (!create_pipe(nr_o_pipes)) { 390 if (!create_pipe(nr_o_pipes)) {
386 info("Creating extra spare pipe"); 391 info("Creating extra spare pipe");
387 info("Loopback %d registered, input: video%d, output: video%d", 392 info("Loopback %d registered, input: video%d, output: video%d",
388 nr_o_pipes, 393 nr_o_pipes,
389 loops[nr_o_pipes]->vloopin->minor, 394 loops[nr_o_pipes]->vloopin->minor,
390 loops[nr_o_pipes]->vloopout->minor 395 loops[nr_o_pipes]->vloopout->minor
391 ); 396 );
392 nr_o_pipes++; 397 nr_o_pipes++;
393 } 398 }
394 } 399 }
395 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,27) 400 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,27)
396 loops[nr]->pid = current->pid; 401 loops[nr]->pid = current->pid;
397 #else 402 #else
398 // TODO : Check in stable 2.6.27 403 // TODO : Check in stable 2.6.27
399 loops[nr]->pid = task_pid(find_task_by_vpid(current->pid)); 404 loops[nr]->pid = task_pid(find_task_by_vpid(current->pid));
400 //loops[nr]->pid = task_pid(current); 405 //loops[nr]->pid = task_pid(current);
401 #endif 406 #endif
402 407
403 if (debug > LOG_NODEBUG) 408 if (debug > LOG_NODEBUG)
404 info("Current pid %d", current->pid); 409 info("Current pid %d", current->pid);
405 } 410 }
406 return 0; 411 return 0;
407 } 412 }
408 413
409 static int vloopback_release(struct inode * inod, struct file *f) 414 static int vloopback_release(struct inode * inod, struct file *f)
410 { 415 {
411 struct video_device *loopdev = video_devdata(f); 416 struct video_device *loopdev = video_devdata(f);
412 priv_ptr ptr = (priv_ptr)loopdev->priv; 417 priv_ptr ptr = (priv_ptr)loopdev->priv;
413 int nr = ptr->pipenr; 418 int nr = ptr->pipenr;
414 419
415 if (debug > LOG_NODEBUG) 420 if (debug > LOG_NODEBUG)
416 info("Video loopback %d", nr); 421 info("Video loopback %d", nr);
417 422
418 if (ptr->in) { 423 if (ptr->in) {
419 down(&loops[nr]->lock); 424 down(&loops[nr]->lock);
420 if (loops[nr]->buffer && !loops[nr]->ropen) { 425 if (loops[nr]->buffer && !loops[nr]->ropen) {
421 rvfree(loops[nr]->buffer, loops[nr]->buflength * N_BUFFS); 426 rvfree(loops[nr]->buffer, loops[nr]->buflength * num_buffers);
422 loops[nr]->buffer = NULL; 427 loops[nr]->buffer = NULL;
423 } 428 }
424 up(&loops[nr]->lock); 429
425 loops[nr]->frameswrite++; 430 up(&loops[nr]->lock);
426 if (waitqueue_active(&loops[nr]->wait)) 431 loops[nr]->frameswrite++;
427 wake_up(&loops[nr]->wait); 432
428 433 if (waitqueue_active(&loops[nr]->wait))
429 loops[nr]->width = 0; 434 wake_up(&loops[nr]->wait);
430 loops[nr]->height = 0; 435
431 loops[nr]->palette = 0; 436 loops[nr]->width = 0;
432 loops[nr]->wopen = 0; 437 loops[nr]->height = 0;
433 pipesused--; 438 loops[nr]->palette = 0;
434 } else { 439 loops[nr]->wopen = 0;
435 down(&loops[nr]->lock); 440 pipesused--;
436 if (loops[nr]->buffer && !loops[nr]->wopen) { 441 } else {
437 rvfree(loops[nr]->buffer, loops[nr]->buflength * N_BUFFS); 442 down(&loops[nr]->lock);
438 loops[nr]->buffer = NULL; 443
439 } 444 if (loops[nr]->buffer && !loops[nr]->wopen) {
440 up(&loops[nr]->lock); 445 rvfree(loops[nr]->buffer, loops[nr]->buflength * num_buffers);
441 loops[nr]->ropen = 0; 446 loops[nr]->buffer = NULL;
442 if (loops[nr]->zerocopy && loops[nr]->buffer) { 447 }
443 loops[nr]->ioctlnr = 0; 448
444 loops[nr]->ioctllength = 0; 449 up(&loops[nr]->lock);
450 loops[nr]->ropen = 0;
451
452 if (loops[nr]->zerocopy && loops[nr]->buffer) {
453 loops[nr]->ioctlnr = 0;
454 loops[nr]->ioctllength = 0;
445 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,27) 455 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,27)
446 kill_proc(loops[nr]->pid, SIGIO, 1); 456 kill_proc(loops[nr]->pid, SIGIO, 1);
447 #else 457 #else
448 kill_pid(loops[nr]->pid, SIGIO, 1); 458 kill_pid(loops[nr]->pid, SIGIO, 1);
449 #endif 459 #endif
450 } 460 }
451 } 461 }
452 462
453 return 0; 463 return 0;
454 } 464 }
455 465
456 static ssize_t vloopback_write(struct file *f, const char *buf, 466 static ssize_t vloopback_write(struct file *f, const char *buf,
457 size_t count, loff_t *offset) 467 size_t count, loff_t *offset)
458 { 468 {
459 struct video_device *loopdev = video_devdata(f); 469 struct video_device *loopdev = video_devdata(f);
460 priv_ptr ptr = (priv_ptr)loopdev->priv; 470 priv_ptr ptr = (priv_ptr)loopdev->priv;
461 int nr = ptr->pipenr; 471 int nr = ptr->pipenr;
462 unsigned long realcount = count; 472 unsigned long realcount = count;
463 473
464 if (debug > LOG_IOCTL) 474 if (debug > LOG_IOCTL)
465 info("Video loopback %d", nr); 475 info("Video loopback %d", nr);
466 476
467 if (!ptr->in) 477 if (!ptr->in)
468 return -EINVAL; 478 return -EINVAL;
469 479
470 if (loops[nr]->zerocopy) 480 if (loops[nr]->zerocopy)
471 return -EINVAL; 481 return -EINVAL;
472 482
473 if (loops[nr]->buffer == NULL) 483 if (loops[nr]->buffer == NULL)
474 return -EINVAL; 484 return -EINVAL;
475 485
476 /* Anybody want some pictures??? */ 486 /* Anybody want some pictures??? */
477 if (!waitqueue_active(&loops[nr]->wait)) { 487 if (!waitqueue_active(&loops[nr]->wait)) {
478 loops[nr]->framesdumped++; 488 loops[nr]->framesdumped++;
479 return realcount; 489 return realcount;
480 } 490 }
481 491
482 down(&loops[nr]->lock); 492 down(&loops[nr]->lock);
483 if (!loops[nr]->buffer) { 493 if (!loops[nr]->buffer) {
484 up(&loops[nr]->lock); 494 up(&loops[nr]->lock);
485 return -EINVAL; 495 return -EINVAL;
486 } 496 }
487 497
488 if (realcount > loops[nr]->buflength) { 498 if (realcount > loops[nr]->buflength) {
489 realcount = loops[nr]->buflength; 499 realcount = loops[nr]->buflength;
490 info("Too much data for Video loopback %d ! Only %ld bytes used.", 500 info("Too much data for Video loopback %d ! Only %ld bytes used.",
491 nr, realcount); 501 nr, realcount);
492 } 502 }
493 503
494 if (copy_from_user(loops[nr]->buffer + loops[nr]->frame * loops[nr]->buflength, 504 if (copy_from_user(loops[nr]->buffer + loops[nr]->frame * loops[nr]->buflength,
495 buf, realcount)) 505 buf, realcount))
496 return -EFAULT; 506 return -EFAULT;
497 507
498 loops[nr]->frame = 0; 508 loops[nr]->frame = 0;
499 up(&loops[nr]->lock); 509 up(&loops[nr]->lock);
500 510
501 loops[nr]->frameswrite++; 511 loops[nr]->frameswrite++;
502 wake_up(&loops[nr]->wait); 512 wake_up(&loops[nr]->wait);
503 513
504 return realcount; 514 return realcount;
505 } 515 }
506 516
507 static ssize_t vloopback_read(struct file * f, char * buf, size_t count, 517 static ssize_t vloopback_read(struct file * f, char * buf, size_t count,
508 loff_t *offset) 518 loff_t *offset)
509 { 519 {
510 struct video_device *loopdev = video_devdata(f); 520 struct video_device *loopdev = video_devdata(f);
511 priv_ptr ptr = (priv_ptr)loopdev->priv; 521 priv_ptr ptr = (priv_ptr)loopdev->priv;
512 int nr = ptr->pipenr; 522 int nr = ptr->pipenr;
513 unsigned long realcount = count; 523 unsigned long realcount = count;
514 524
515 if (debug > LOG_IOCTL) 525 if (debug > LOG_IOCTL)
516 info("Video loopback %d", nr); 526 info("Video loopback %d", nr);
517 527
518 if (loops[nr]->zerocopy) { 528 if (loops[nr]->zerocopy) {
519 if (ptr->in) { 529 if (ptr->in) {
520 if (realcount > loops[nr]->ioctllength + sizeof(unsigned long int)) 530 if (realcount > loops[nr]->ioctllength + sizeof(unsigned long int))
521 realcount = loops[nr]->ioctllength + sizeof(unsigned long int); 531 realcount = loops[nr]->ioctllength + sizeof(unsigned long int);
522 532
523 if (copy_to_user(buf , &loops[nr]->ioctlnr, sizeof(unsigned long int))) 533 if (copy_to_user(buf , &loops[nr]->ioctlnr, sizeof(unsigned long int)))
524 return -EFAULT; 534 return -EFAULT;
525 535
526 if (copy_to_user(buf + sizeof(unsigned long int), loops[nr]->ioctldata, 536 if (copy_to_user(buf + sizeof(unsigned long int), loops[nr]->ioctldata,
527 realcount - sizeof(unsigned long int))) 537 realcount - sizeof(unsigned long int)))
528 return -EFAULT; 538 return -EFAULT;
529 539
530 if (loops[nr]->ioctlnr == 0) 540 if (loops[nr]->ioctlnr == 0)
531 loops[nr]->ioctlnr = -1; 541 loops[nr]->ioctlnr = -1;
532 542
533 return realcount; 543 return realcount;
534 } else { 544 } else {
535 struct video_window vidwin; 545 struct video_window vidwin;
536 struct video_mmap vidmmap; 546 struct video_mmap vidmmap;
537 struct video_picture vidpic; 547 struct video_picture vidpic;
538 548
539 fake_ioctl(nr, VIDIOCGWIN, &vidwin); 549 fake_ioctl(nr, VIDIOCGWIN, &vidwin);
540 fake_ioctl(nr, VIDIOCGPICT, &vidpic); 550 fake_ioctl(nr, VIDIOCGPICT, &vidpic);
541 551
542 vidmmap.height = vidwin.height; 552 vidmmap.height = vidwin.height;
543 vidmmap.width = vidwin.width; 553 vidmmap.width = vidwin.width;
544 vidmmap.format = vidpic.palette; 554 vidmmap.format = vidpic.palette;
545 vidmmap.frame = 0; 555 vidmmap.frame = 0;
546 556
547 if (fake_ioctl(nr, VIDIOCMCAPTURE, &vidmmap)) 557 if (fake_ioctl(nr, VIDIOCMCAPTURE, &vidmmap))
548 return 0; 558 return 0;
549 559
550 if (fake_ioctl(nr, VIDIOCSYNC, &vidmmap)) 560 if (fake_ioctl(nr, VIDIOCSYNC, &vidmmap))
551 return 0; 561 return 0;
552 562
553 realcount = vidwin.height * vidwin.width * vidpic.depth; 563 realcount = vidwin.height * vidwin.width * vidpic.depth;
554 } 564 }
555 } 565 }
556 566
557 if (ptr->in) 567 if (ptr->in)
558 return -EINVAL; 568 return -EINVAL;
559 569
560 if (realcount > loops[nr]->buflength) { 570 if (realcount > loops[nr]->buflength) {
561 realcount = loops[nr]->buflength; 571 realcount = loops[nr]->buflength;
562 info("Not so much data in buffer! for Video loopback %d", nr); 572 info("Not so much data in buffer! for Video loopback %d", nr);
563 } 573 }
564 574
565 if (!loops[nr]->zerocopy) { 575 if (!loops[nr]->zerocopy) {
566 #if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0) 576 #if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)
567 unsigned long fw = loops[nr]->frameswrite; 577 unsigned long fw = loops[nr]->frameswrite;
568 578
569 wait_event_interruptible(loops[nr]->wait, fw != loops[nr]->frameswrite); 579 wait_event_interruptible(loops[nr]->wait, fw != loops[nr]->frameswrite);
570 #else 580 #else
571 interruptible_sleep_on(&loops[nr]->wait); 581 interruptible_sleep_on(&loops[nr]->wait);
572 #endif 582 #endif
573 } 583 }
574 584
575 down(&loops[nr]->lock); 585 down(&loops[nr]->lock);
576 if (!loops[nr]->buffer) { 586 if (!loops[nr]->buffer) {
577 up(&loops[nr]->lock); 587 up(&loops[nr]->lock);
578 return 0; 588 return 0;
579 } 589 }
580 590
581 if (copy_to_user(buf, loops[nr]->buffer, realcount)) 591 if (copy_to_user(buf, loops[nr]->buffer, realcount))
582 return -EFAULT; 592 return -EFAULT;
583 593
584 up(&loops[nr]->lock); 594 up(&loops[nr]->lock);
585 595
586 loops[nr]->framesread++; 596 loops[nr]->framesread++;
587 return realcount; 597 return realcount;
588 } 598 }
589 599
590 static int vloopback_mmap(struct file *f, struct vm_area_struct *vma) 600 static int vloopback_mmap(struct file *f, struct vm_area_struct *vma)
591 { 601 {
592 struct video_device *loopdev = video_devdata(f); 602 struct video_device *loopdev = video_devdata(f);
593 priv_ptr ptr = (priv_ptr)loopdev->priv; 603 priv_ptr ptr = (priv_ptr)loopdev->priv;
594 int nr = ptr->pipenr; 604 int nr = ptr->pipenr;
595 unsigned long start = (unsigned long)vma->vm_start; 605 unsigned long start = (unsigned long)vma->vm_start;
596 long size = vma->vm_end - vma->vm_start; 606 long size = vma->vm_end - vma->vm_start;
597 unsigned long page, pos; 607 unsigned long page, pos;
598 608
599 if (debug > LOG_NODEBUG) 609 if (debug > LOG_NODEBUG)
600 info("Video loopback %d", nr); 610 info("Video loopback %d", nr);
601 611
602 down(&loops[nr]->lock); 612 down(&loops[nr]->lock);
603 613
604 if (ptr->in) { 614 if (ptr->in) {
605 loops[nr]->zerocopy = 1; 615 loops[nr]->zerocopy = 1;
606 616
607 if (loops[nr]->ropen) { 617 if (loops[nr]->ropen) {
608 info("Can't change size while opened for read in Video loopback %d", 618 info("Can't change size while opened for read in Video loopback %d",
609 nr); 619 nr);
610 up(&loops[nr]->lock); 620 up(&loops[nr]->lock);
611 return -EINVAL; 621 return -EINVAL;
612 } 622 }
613 623
614 if (!size) { 624 if (!size) {
615 up(&loops[nr]->lock); 625 up(&loops[nr]->lock);
616 info("Invalid size Video loopback %d", nr); 626 info("Invalid size Video loopback %d", nr);
617 return -EINVAL; 627 return -EINVAL;
618 } 628 }
619 629
620 if (loops[nr]->buffer) 630 if (loops[nr]->buffer)
621 rvfree(loops[nr]->buffer, loops[nr]->buflength * N_BUFFS); 631 rvfree(loops[nr]->buffer, loops[nr]->buflength * num_buffers);
622 632
623 loops[nr]->buflength = size; 633 loops[nr]->buflength = size;
624 loops[nr]->buffer = rvmalloc(loops[nr]->buflength * N_BUFFS); 634 loops[nr]->buffer = rvmalloc(loops[nr]->buflength * num_buffers);
625 } 635 }
626 636
627 if (loops[nr]->buffer == NULL) { 637 if (loops[nr]->buffer == NULL) {
628 up(&loops[nr]->lock); 638 up(&loops[nr]->lock);
629 return -EINVAL; 639 return -EINVAL;
630 } 640 }
631 641
632 if (size > (((N_BUFFS * loops[nr]->buflength) + PAGE_SIZE - 1) 642 if (size > (((num_buffers * loops[nr]->buflength) + PAGE_SIZE - 1)
633 & ~(PAGE_SIZE - 1))) { 643 & ~(PAGE_SIZE - 1))) {
634 up(&loops[nr]->lock); 644 up(&loops[nr]->lock);
635 return -EINVAL; 645 return -EINVAL;
636 } 646 }
637 647
638 pos = (unsigned long)loops[nr]->buffer; 648 pos = (unsigned long)loops[nr]->buffer;
639 649
640 while (size > 0) { 650 while (size > 0) {
641 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,9) 651 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,9)
642 page = kvirt_to_pa(pos); 652 page = kvirt_to_pa(pos);
643 if (remap_page_range(vma,start, page, PAGE_SIZE, PAGE_SHARED)) { 653 if (remap_page_range(vma,start, page, PAGE_SIZE, PAGE_SHARED)) {
644 #else 654 #else
645 page = vmalloc_to_pfn((void *)pos); 655 page = vmalloc_to_pfn((void *)pos);
646 if (remap_pfn_range(vma, start, page, PAGE_SIZE, PAGE_SHARED)) { 656 if (remap_pfn_range(vma, start, page, PAGE_SIZE, PAGE_SHARED)) {
647 #endif 657 #endif
648 up(&loops[nr]->lock); 658 up(&loops[nr]->lock);
649 return -EAGAIN; 659 return -EAGAIN;
650 } 660 }
651 start += PAGE_SIZE; 661 start += PAGE_SIZE;
652 pos += PAGE_SIZE; 662 pos += PAGE_SIZE;
653 size -= PAGE_SIZE; 663 size -= PAGE_SIZE;
654 } 664 }
655 665
656 up(&loops[nr]->lock); 666 up(&loops[nr]->lock);
657 667
658 return 0; 668 return 0;
659 } 669 }
660 670
661 static int vloopback_ioctl(struct inode *inod, struct file *f, unsigned int cmd, 671 static int vloopback_ioctl(struct inode *inod, struct file *f, unsigned int cmd,
662 unsigned long arg) 672 unsigned long arg)
663 { 673 {
664 struct video_device *loopdev = video_devdata(f); 674 struct video_device *loopdev = video_devdata(f);
665 priv_ptr ptr = (priv_ptr)loopdev->priv; 675 priv_ptr ptr = (priv_ptr)loopdev->priv;
666 int nr = ptr->pipenr; 676 int nr = ptr->pipenr;
667 int i; 677 int i;
668 678
669 if (debug > LOG_NODEBUG) 679 if (debug > LOG_NODEBUG)
670 info("Video loopback %d cmd %u", nr, cmd); 680 info("Video loopback %d cmd %u", nr, cmd);
671 681
672 if (loops[nr]->zerocopy) { 682 if (loops[nr]->zerocopy) {
673 if (!ptr->in) { 683 if (!ptr->in) {
674 loops[nr]->ioctlnr = cmd; 684 loops[nr]->ioctlnr = cmd;
675 loops[nr]->ioctllength = _IOC_SIZE(cmd); 685 loops[nr]->ioctllength = _IOC_SIZE(cmd);
676 /* info("DEBUG: vl_ioctl: !loop->in"); */ 686 /* info("DEBUG: vl_ioctl: !loop->in"); */
677 /* info("DEBUG: vl_ioctl: cmd %lu", cmd); */ 687 /* info("DEBUG: vl_ioctl: cmd %lu", cmd); */
678 /* info("DEBUG: vl_ioctl: len %lu", loops[nr]->ioctllength); */ 688 /* info("DEBUG: vl_ioctl: len %lu", loops[nr]->ioctllength); */
679 if (copy_from_user(loops[nr]->ioctldata, (void*)arg, _IOC_SIZE(cmd))) 689 if (copy_from_user(loops[nr]->ioctldata, (void*)arg, _IOC_SIZE(cmd)))
680 return -EFAULT; 690 return -EFAULT;
681 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,27) 691 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,27)
682 kill_proc(loops[nr]->pid, SIGIO, 1); 692 kill_proc(loops[nr]->pid, SIGIO, 1);
683 #else 693 #else
684 kill_pid(loops[nr]->pid, SIGIO, 1); 694 kill_pid(loops[nr]->pid, SIGIO, 1);
685 #endif 695 #endif
686 696
687 #if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0) 697 #if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)
688 wait_event_interruptible(loops[nr]->wait, loops[nr]->ioctlnr == -1); 698 wait_event_interruptible(loops[nr]->wait, loops[nr]->ioctlnr == -1);
689 #else 699 #else
690 interruptible_sleep_on(&loops[nr]->wait); 700 interruptible_sleep_on(&loops[nr]->wait);
691 #endif 701 #endif
692 702
693 if (loops[nr]->invalid_ioctl) { 703 if (loops[nr]->invalid_ioctl) {
694 info ("There was an invalid ioctl in Video loopback %d", nr); 704 info ("There was an invalid ioctl in Video loopback %d", nr);
695 loops[nr]->invalid_ioctl = 0; 705 loops[nr]->invalid_ioctl = 0;
696 return -ENOTTY; 706 return -ENOTTY;
697 } 707 }
698 708
699 if (cmd & IOC_IN && !(cmd & IOC_OUT)) { 709 if (cmd & IOC_IN && !(cmd & IOC_OUT)) {
700 //info("DEBUG: vl_ioctl: cmd & IOC_IN 1"); 710 //info("DEBUG: vl_ioctl: cmd & IOC_IN 1");
701 if (memcmp(loops[nr]->ioctlretdata, loops[nr]->ioctldata, _IOC_SIZE(cmd))) 711 if (memcmp(loops[nr]->ioctlretdata, loops[nr]->ioctldata, _IOC_SIZE(cmd)))
702 return -EINVAL; 712 return -EINVAL;
703 713
704 //info("DEBUG: vl_ioctl: cmd & IOC_IN 2"); 714 //info("DEBUG: vl_ioctl: cmd & IOC_IN 2");
705 return 0;
706 } else {
707 if (copy_to_user((void*)arg, loops[nr]->ioctlretdata, _IOC_SIZE(cmd)))
708 return -EFAULT;
709 //info("DEBUG: vl_ioctl: !(cmd & IOC_IN) 1");
710 return 0;
711 }
712 } else {
713 if ((loops[nr]->ioctlnr != cmd) && (cmd != (VIDIOCSINVALID))) {
714 /* wrong ioctl */
715 info("Wrong IOCTL %u in Video loopback %d", cmd, nr);
716 return 0; 715 return 0;
717 } 716 } else {
718 717 if (copy_to_user((void*)arg, loops[nr]->ioctlretdata, _IOC_SIZE(cmd)))
719 if (cmd == VIDIOCSINVALID) { 718 return -EFAULT;
720 loops[nr]->invalid_ioctl = 1; 719 //info("DEBUG: vl_ioctl: !(cmd & IOC_IN) 1");
721 } else if (copy_from_user(loops[nr]->ioctlretdata, 720 return 0;
721 }
722 } else {
723 if ((loops[nr]->ioctlnr != cmd) && (cmd != (VIDIOCSINVALID))) {
724 /* wrong ioctl */
725 info("Wrong IOCTL %u in Video loopback %d", cmd, nr);
726 return 0;
727 }
728
729 if (cmd == VIDIOCSINVALID) {
730 loops[nr]->invalid_ioctl = 1;
731 } else if (copy_from_user(loops[nr]->ioctlretdata,
722 (void*)arg, loops[nr]->ioctllength)) { 732 (void*)arg, loops[nr]->ioctllength)) {
723 return -EFAULT; 733 return -EFAULT;
724 } 734 }
725 735
726 loops[nr]->ioctlnr = -1; 736 loops[nr]->ioctlnr = -1;
727 737
728 if (waitqueue_active(&loops[nr]->wait)) 738 if (waitqueue_active(&loops[nr]->wait))
729 wake_up(&loops[nr]->wait); 739 wake_up(&loops[nr]->wait);
730 740
731 return 0; 741 return 0;
732 } 742 }
733 } 743 }
734 744
735 switch(cmd) 745 switch(cmd)
736 { 746 {
737 /* Get capabilities */ 747 /* Get capabilities */
738 case VIDIOCGCAP: 748 case VIDIOCGCAP:
739 { 749 {
740 struct video_capability b; 750 struct video_capability b;
741 if (ptr->in) { 751 if (ptr->in) {
742 sprintf(b.name, "Video loopback %d input", nr); 752 sprintf(b.name, "Video loopback %d input", nr);
743 b.type = 0; 753 b.type = 0;
744 } else { 754 } else {
745 sprintf(b.name, "Video loopback %d output", nr); 755 sprintf(b.name, "Video loopback %d output", nr);
746 b.type = VID_TYPE_CAPTURE; 756 b.type = VID_TYPE_CAPTURE;
747 } 757 }
748 758
749 b.channels = 1; 759 b.channels = 1;
750 b.audios = 0; 760 b.audios = 0;
751 b.maxwidth = loops[nr]->width; 761 b.maxwidth = loops[nr]->width;
752 b.maxheight = loops[nr]->height; 762 b.maxheight = loops[nr]->height;
753 b.minwidth = 20; 763 b.minwidth = 20;
754 b.minheight = 20; 764 b.minheight = 20;
755 765
756 if (copy_to_user((void*)arg, &b, sizeof(b))) 766 if (copy_to_user((void*)arg, &b, sizeof(b)))
757 return -EFAULT; 767 return -EFAULT;
758 768
759 return 0; 769 return 0;
760 } 770 }
761 /* Get channel info (sources) */ 771 /* Get channel info (sources) */
762 case VIDIOCGCHAN: 772 case VIDIOCGCHAN:
763 { 773 {
764 struct video_channel v; 774 struct video_channel v;
765 if (copy_from_user(&v, (void*)arg, sizeof(v))) 775 if (copy_from_user(&v, (void*)arg, sizeof(v)))
766 return -EFAULT; 776 return -EFAULT;
767 777
768 if (v.channel != 0) { 778 if (v.channel != 0) {
769 info("VIDIOCGCHAN: Invalid Channel, was %d", v.channel); 779 info("VIDIOCGCHAN: Invalid Channel, was %d", v.channel);
770 v.channel = 0; 780 v.channel = 0;
771 //return -EINVAL; 781 //return -EINVAL;
772 } 782 }
773 783
774 v.flags = 0; 784 v.flags = 0;
775 v.tuners = 0; 785 v.tuners = 0;
776 v.norm = 0; 786 v.norm = 0;
777 v.type = VIDEO_TYPE_CAMERA; 787 v.type = VIDEO_TYPE_CAMERA;
778 /*strcpy(v.name, "Loopback"); -- tibit */ 788 /*strcpy(v.name, "Loopback"); -- tibit */
779 strcpy(v.name, "Composite1"); 789 strcpy(v.name, "Composite1");
780 790
781 if (copy_to_user((void*)arg, &v, sizeof(v))) 791 if (copy_to_user((void*)arg, &v, sizeof(v)))
782 return -EFAULT; 792 return -EFAULT;
783 793
784 return 0; 794 return 0;
785 } 795 }
786 /* Set channel */ 796 /* Set channel */
787 case VIDIOCSCHAN: 797 case VIDIOCSCHAN:
788 { 798 {
789 int v; 799 int v;
790 800
791 if (copy_from_user(&v, (void*)arg, sizeof(v))) 801 if (copy_from_user(&v, (void*)arg, sizeof(v)))
792 return -EFAULT; 802 return -EFAULT;
793 803
794 if (v != 0) { 804 if (v != 0) {
795 info("VIDIOCSCHAN: Invalid Channel, was %d", v); 805 info("VIDIOCSCHAN: Invalid Channel, was %d", v);
796 return -EINVAL; 806 return -EINVAL;
797 } 807 }
798 808
799 return 0; 809 return 0;
800 } 810 }
801 /* Get tuner abilities */ 811 /* Get tuner abilities */
802 case VIDIOCGTUNER: 812 case VIDIOCGTUNER:
803 { 813 {
804 struct video_tuner v; 814 struct video_tuner v;
805 815
806 if (copy_from_user(&v, (void*)arg, sizeof(v)) != 0) 816 if (copy_from_user(&v, (void*)arg, sizeof(v)) != 0)
807 return -EFAULT; 817 return -EFAULT;
808 818
809 if (v.tuner) { 819 if (v.tuner) {
810 info("VIDIOCGTUNER: Invalid Tuner, was %d", v.tuner); 820 info("VIDIOCGTUNER: Invalid Tuner, was %d", v.tuner);
811 return -EINVAL; 821 return -EINVAL;
812 } 822 }
813 823
814 strcpy(v.name, "Format"); 824 strcpy(v.name, "Format");
815 v.rangelow = 0; 825 v.rangelow = 0;
816 v.rangehigh = 0; 826 v.rangehigh = 0;
817 v.flags = 0; 827 v.flags = 0;
818 v.mode = VIDEO_MODE_AUTO; 828 v.mode = VIDEO_MODE_AUTO;
819 829
820 if (copy_to_user((void*)arg,&v, sizeof(v)) != 0) 830 if (copy_to_user((void*)arg,&v, sizeof(v)) != 0)
821 return -EFAULT; 831 return -EFAULT;
822 832
823 return 0; 833 return 0;
824 } 834 }
825 /* Get picture properties */ 835 /* Get picture properties */
826 case VIDIOCGPICT: 836 case VIDIOCGPICT:
827 { 837 {
828 struct video_picture p; 838 struct video_picture p;
829 839
830 p.colour = 0x8000; 840 p.colour = 0x8000;
831 p.hue = 0x8000; 841 p.hue = 0x8000;
832 p.brightness = 0x8000; 842 p.brightness = 0x8000;
833 p.contrast = 0x8000; 843 p.contrast = 0x8000;
834 p.whiteness = 0x8000; 844 p.whiteness = 0x8000;
835 p.depth = 0x8000; 845 p.depth = 0x8000;
836 p.palette = loops[nr]->palette; 846 p.palette = loops[nr]->palette;
837 847
838 if (copy_to_user((void*)arg, &p, sizeof(p))) 848 if (copy_to_user((void*)arg, &p, sizeof(p)))
839 return -EFAULT; 849 return -EFAULT;
840 850
841 return 0; 851 return 0;
842 } 852 }
843 /* Set picture properties */ 853 /* Set picture properties */
844 case VIDIOCSPICT: 854 case VIDIOCSPICT:
845 { 855 {
846 struct video_picture p; 856 struct video_picture p;
847 857
848 if (copy_from_user(&p, (void*)arg, sizeof(p))) 858 if (copy_from_user(&p, (void*)arg, sizeof(p)))
849 return -EFAULT; 859 return -EFAULT;
850 860
851 if (!ptr->in) { 861 if (!ptr->in) {
852 if (p.palette != loops[nr]->palette) 862 if (p.palette != loops[nr]->palette)
853 return -EINVAL; 863 return -EINVAL;
854 } else { 864 } else {
855 loops[nr]->palette = p.palette; 865 loops[nr]->palette = p.palette;
856 } 866 }
857 867
858 return 0; 868 return 0;
859 } 869 }
860 /* Get the video overlay window */ 870 /* Get the video overlay window */
861 case VIDIOCGWIN: 871 case VIDIOCGWIN:
862 { 872 {
863 struct video_window vw; 873 struct video_window vw;
864 874
865 vw.x = 0; 875 vw.x = 0;
866 vw.y = 0; 876 vw.y = 0;
867 vw.width = loops[nr]->width; 877 vw.width = loops[nr]->width;
868 vw.height = loops[nr]->height; 878 vw.height = loops[nr]->height;
869 vw.chromakey = 0; 879 vw.chromakey = 0;
870 vw.flags = 0; 880 vw.flags = 0;
871 vw.clipcount = 0; 881 vw.clipcount = 0;
872 882
873 if (copy_to_user((void*)arg, &vw, sizeof(vw))) 883 if (copy_to_user((void*)arg, &vw, sizeof(vw)))
874 return -EFAULT; 884 return -EFAULT;
875 885
876 return 0; 886 return 0;
877 } 887 }
878 /* Set the video overlay window - passes clip list for hardware smarts , chromakey etc */ 888 /* Set the video overlay window - passes clip list for hardware smarts , chromakey etc */
879 case VIDIOCSWIN: 889 case VIDIOCSWIN:
880 { 890 {
881 struct video_window vw; 891 struct video_window vw;
882 892
883 if (copy_from_user(&vw, (void*)arg, sizeof(vw))) 893 if (copy_from_user(&vw, (void*)arg, sizeof(vw)))
884 return -EFAULT; 894 return -EFAULT;
885 895
886 if (vw.flags) 896 if (vw.flags)
887 return -EINVAL; 897 return -EINVAL;
888 898
889 if (vw.clipcount) 899 if (vw.clipcount)
890 return -EINVAL; 900 return -EINVAL;
891 901
892 if (loops[nr]->height == vw.height && 902 if (loops[nr]->height == vw.height &&
893 loops[nr]->width == vw.width) 903 loops[nr]->width == vw.width)
894 return 0; 904 return 0;
895 905
896 if (!ptr->in) { 906 if (!ptr->in) {
897 return -EINVAL; 907 return -EINVAL;
898 } else { 908 } else {
899 loops[nr]->height = vw.height; 909 loops[nr]->height = vw.height;
900 loops[nr]->width = vw.width; 910 loops[nr]->width = vw.width;
901 /* Make sure nobody is using the buffer while we 911 /* Make sure nobody is using the buffer while we
902 fool around with it. 912 fool around with it.
903 We are also not allowing changes while 913 We are also not allowing changes while
904 somebody using mmap has the output open. 914 somebody using mmap has the output open.
905 */ 915 */
906 down(&loops[nr]->lock); 916 down(&loops[nr]->lock);
907 if (loops[nr]->ropen) { 917 if (loops[nr]->ropen) {
908 info("Can't change size while opened for read"); 918 info("Can't change size while opened for read");
909 up(&loops[nr]->lock); 919 up(&loops[nr]->lock);
910 return -EINVAL; 920 return -EINVAL;
911 } 921 }
912 922
913 if (loops[nr]->buffer) 923 if (loops[nr]->buffer)
914 rvfree(loops[nr]->buffer, loops[nr]->buflength * N_BUFFS); 924 rvfree(loops[nr]->buffer, loops[nr]->buflength * num_buffers);
915 925
916 loops[nr]->buflength = vw.width * vw.height * 4; 926 loops[nr]->buflength = vw.width * vw.height * 4;
917 loops[nr]->buffer = rvmalloc(loops[nr]->buflength * N_BUFFS); 927 loops[nr]->buffer = rvmalloc(loops[nr]->buflength * num_buffers);
918 up(&loops[nr]->lock); 928 up(&loops[nr]->lock);
919 } 929 }
920 return 0; 930 return 0;
921 } 931 }
922 /* Memory map buffer info */ 932 /* Memory map buffer info */
923 case VIDIOCGMBUF: 933 case VIDIOCGMBUF:
924 { 934 {
925 struct video_mbuf vm; 935 struct video_mbuf vm;
926 936
927 vm.size = loops[nr]->buflength * N_BUFFS; 937 vm.size = loops[nr]->buflength * num_buffers;
928 vm.frames = N_BUFFS; 938 vm.frames = num_buffers;
929 for (i = 0; i < vm.frames; i++) 939 for (i = 0; i < vm.frames; i++)
930 vm.offsets[i] = i * loops[nr]->buflength; 940 vm.offsets[i] = i * loops[nr]->buflength;
931 941
932 if (copy_to_user((void*)arg, &vm, sizeof(vm))) 942 if (copy_to_user((void*)arg, &vm, sizeof(vm)))
933 return -EFAULT; 943 return -EFAULT;
934 944
935 return 0; 945 return 0;
936 } 946 }
937 /* Grab frames */ 947 /* Grab frames */
938 case VIDIOCMCAPTURE: 948 case VIDIOCMCAPTURE:
939 { 949 {
940 struct video_mmap vm; 950 struct video_mmap vm;
941 951
942 if (ptr->in) 952 if (ptr->in)
943 return -EINVAL; 953 return -EINVAL;
944 954
945 if (!loops[nr]->buffer) 955 if (!loops[nr]->buffer)
946 return -EINVAL; 956 return -EINVAL;
947 957
948 if (copy_from_user(&vm, (void*)arg, sizeof(vm))) 958 if (copy_from_user(&vm, (void*)arg, sizeof(vm)))
949 return -EFAULT; 959 return -EFAULT;
950 960
951 if (vm.format != loops[nr]->palette) 961 if (vm.format != loops[nr]->palette)
952 return -EINVAL; 962 return -EINVAL;
953 963
954 if (vm.frame > N_BUFFS) 964 if (vm.frame > num_buffers)
955 return -EINVAL; 965 return -EINVAL;
956 966
957 return 0; 967 return 0;
958 } 968 }
959 /* Sync with mmap grabbing */ 969 /* Sync with mmap grabbing */
960 case VIDIOCSYNC: 970 case VIDIOCSYNC:
961 { 971 {
962 int frame; 972 int frame;
963 unsigned long fw; 973 unsigned long fw;
964 974
965 if (copy_from_user((void *)&frame, (void*)arg, sizeof(int))) 975 if (copy_from_user((void *)&frame, (void*)arg, sizeof(int)))
966 return -EFAULT; 976 return -EFAULT;
967 977
968 if (ptr->in) 978 if (ptr->in)
969 return -EINVAL; 979 return -EINVAL;
970 980
971 if (!loops[nr]->buffer) 981 if (!loops[nr]->buffer)
972 return -EINVAL; 982 return -EINVAL;
973 983
974 /* Ok, everything should be alright since the program 984 /* Ok, everything should be alright since the program
975 should have called VIDIOMCAPTURE and we are ready to 985 should have called VIDIOMCAPTURE and we are ready to
976 do the 'capturing' */ 986 do the 'capturing' */
977 if (frame > 1) 987 //if (frame > 1)
978 return -EINVAL; 988 if (frame > num_buffers-1)
979 989 return -EINVAL;
980 loops[nr]->frame = frame; 990
991 loops[nr]->frame = frame;
981 #if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0) 992 #if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)
982 fw = loops[nr]->frameswrite; 993 fw = loops[nr]->frameswrite;
983 wait_event_interruptible(loops[nr]->wait, fw != loops[nr]->frameswrite); 994 wait_event_interruptible(loops[nr]->wait, fw != loops[nr]->frameswrite);
984 #else 995 #else
985 interruptible_sleep_on(&loops[nr]->wait); 996 interruptible_sleep_on(&loops[nr]->wait);
986 #endif 997 #endif
987 if (!loops[nr]->buffer) /* possibly released during sleep */ 998 if (!loops[nr]->buffer) /* possibly released during sleep */
988 return -EINVAL; 999 return -EINVAL;
989 1000
990 loops[nr]->framesread++; 1001 loops[nr]->framesread++;
991 1002
992 return 0; 1003 return 0;
993 } 1004 }
994 /* Get attached units */ 1005 /* Get attached units */
995 case VIDIOCGUNIT: 1006 case VIDIOCGUNIT:
996 { 1007 {
997 struct video_unit vu; 1008 struct video_unit vu;
998 1009
999 if (ptr->in) 1010 if (ptr->in)
1000 vu.video = loops[nr]->vloopout->minor; 1011 vu.video = loops[nr]->vloopout->minor;
1001 else 1012 else
1002 vu.video = loops[nr]->vloopin->minor; 1013 vu.video = loops[nr]->vloopin->minor;
1003 1014
1004 vu.vbi = VIDEO_NO_UNIT; 1015 vu.vbi = VIDEO_NO_UNIT;
1005 vu.radio = VIDEO_NO_UNIT; 1016 vu.radio = VIDEO_NO_UNIT;
1006 vu.audio = VIDEO_NO_UNIT; 1017 vu.audio = VIDEO_NO_UNIT;
1007 vu.teletext = VIDEO_NO_UNIT; 1018 vu.teletext = VIDEO_NO_UNIT;
1008 1019
1009 if (copy_to_user((void*)arg, &vu, sizeof(vu))) 1020 if (copy_to_user((void*)arg, &vu, sizeof(vu)))
1010 return -EFAULT; 1021 return -EFAULT;
1011 1022
1012 return 0; 1023 return 0;
1013 } 1024 }
1014 /* Get frame buffer */ 1025 /* Get frame buffer */
1015 case VIDIOCGFBUF: 1026 case VIDIOCGFBUF:
1016 { 1027 {
1017 struct video_buffer vb; 1028 struct video_buffer vb;
1018 1029
1019 memset(&vb, 0, sizeof(vb)); 1030 memset(&vb, 0, sizeof(vb));
1020 vb.base = NULL; 1031 vb.base = NULL;
1021 1032
1022 if (copy_to_user((void *)arg, (void *)&vb, sizeof(vb))) 1033 if (copy_to_user((void *)arg, (void *)&vb, sizeof(vb)))
1023 return -EFAULT; 1034 return -EFAULT;
1024 1035
1025 return 0; 1036 return 0;
1026 } 1037 }
1027 /* Start, end capture */ 1038 /* Start, end capture */
1028 case VIDIOCCAPTURE: 1039 case VIDIOCCAPTURE:
1029 { 1040 {
1030 int start; 1041 int start;
1031 1042
1032 if (copy_from_user(&start, (void*)arg, sizeof(int))) 1043 if (copy_from_user(&start, (void*)arg, sizeof(int)))
1033 return -EFAULT; 1044 return -EFAULT;
1034 1045
1035 if (start) { 1046 if (start) {
1036 info ("Video loopback %d Capture started", nr); 1047 info ("Video loopback %d Capture started", nr);
1037 } else { 1048 } else {
1038 info ("Video loopback %d Capture stopped", nr); 1049 info ("Video loopback %d Capture stopped", nr);
1039 } 1050 }
1040 1051
1041 return 0; 1052 return 0;
1042 } 1053 }
1043 case VIDIOCGFREQ: 1054 case VIDIOCGFREQ:
1044 case VIDIOCSFREQ: 1055 case VIDIOCSFREQ:
1045 case VIDIOCGAUDIO: 1056 case VIDIOCGAUDIO:
1046 case VIDIOCSAUDIO: 1057 case VIDIOCSAUDIO:
1047 return -EINVAL; 1058 return -EINVAL;
1048 case VIDIOCKEY: 1059 case VIDIOCKEY:
1049 return 0; 1060 return 0;
1050 default: 1061 default:
1051 return -ENOTTY; 1062 return -ENOTTY;
1052 //return -ENOIOCTLCMD; 1063 //return -ENOIOCTLCMD;
1053 } 1064 }
1054 return 0; 1065 return 0;
1055 } 1066 }
1056 1067
1057 static unsigned int vloopback_poll(struct file *f, struct poll_table_struct *wait) 1068 static unsigned int vloopback_poll(struct file *f, struct poll_table_struct *wait)
1058 { 1069 {
1059 struct video_device *loopdev = video_devdata(f); 1070 struct video_device *loopdev = video_devdata(f);
1060 priv_ptr ptr = (priv_ptr)loopdev->priv; 1071 priv_ptr ptr = (priv_ptr)loopdev->priv;
1061 int nr = ptr->pipenr; 1072 int nr = ptr->pipenr;
1062 1073
1063 if (debug > LOG_NODEBUG) 1074 if (debug > LOG_NODEBUG)
1064 info("Video loopback %d", nr); 1075 info("Video loopback %d", nr);
1065 1076
1066 if (loopdev == NULL) 1077 if (loopdev == NULL)
1067 return -EFAULT; 1078 return -EFAULT;
1068 1079
1069 if (!ptr->in) 1080 if (!ptr->in)
1070 return 0; 1081 return 0;
1071 1082
1072 if (loops[nr]->ioctlnr != -1) { 1083 if (loops[nr]->ioctlnr != -1) {
1073 if (loops[nr]->zerocopy) { 1084 if (loops[nr]->zerocopy) {
1074 return (POLLIN | POLLPRI | POLLOUT | POLLRDNORM); 1085 return (POLLIN | POLLPRI | POLLOUT | POLLRDNORM);
1075 } else { 1086 } else {
1076 return (POLLOUT); 1087 return (POLLOUT);
1077 } 1088 }
1078 } 1089 }
1079 return 0; 1090 return 0;
1080 } 1091 }
1081 1092
1082 static struct file_operations fileops_template = 1093 static struct file_operations fileops_template =
1083 { 1094 {
1084 owner: THIS_MODULE, 1095 owner: THIS_MODULE,
1085 open: vloopback_open, 1096 open: vloopback_open,
1086 release: vloopback_release, 1097 release: vloopback_release,
1087 read: vloopback_read, 1098 read: vloopback_read,
1088 write: vloopback_write, 1099 write: vloopback_write,
1089 poll: vloopback_poll, 1100 poll: vloopback_poll,
1090 ioctl: vloopback_ioctl, 1101 ioctl: vloopback_ioctl,
1091 mmap: vloopback_mmap, 1102 #if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,15)
1103 compat_ioctl: v4l_compat_ioctl32,
1104 #endif
1105 mmap: vloopback_mmap,
1092 }; 1106 };
1093 1107
1094 static struct video_device vloopback_template = 1108 static struct video_device vloopback_template =
1095 { 1109 {
1096 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,27) 1110 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,27)
1097 owner: THIS_MODULE, 1111 owner: THIS_MODULE,
1098 type: VID_TYPE_CAPTURE, 1112 type: VID_TYPE_CAPTURE,
1099 #endif 1113 #endif
1100 minor: -1, 1114 minor: -1,
1101 name: "Video Loopback", 1115 name: "Video Loopback",
1102 fops: &fileops_template, 1116 fops: &fileops_template,
1103 #if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0) 1117 #if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)
1104 release: video_device_release, 1118 release: video_device_release,
1105 #endif 1119 #endif
1106 }; 1120 };
1107 1121
1108 static int create_pipe(int nr) 1122 static int create_pipe(int nr)
1109 { 1123 {
1110 int minor_in, minor_out , ret; 1124 int minor_in, minor_out , ret;
1111 1125
1112 if (debug > LOG_NODEBUG) 1126 if (debug > LOG_NODEBUG)
1113 info("Video loopback %d", nr); 1127 info("Video loopback %d", nr);
1114 1128
1115 if (dev_offset == -1) { 1129 if (dev_offset == -1) {
1116 minor_in = minor_out = -1; /* autoassign */ 1130 minor_in = minor_out = -1; /* autoassign */
1117 } else { 1131 } else {
1118 minor_in = 2 * nr + dev_offset; 1132 minor_in = 2 * nr + dev_offset;
1119 minor_out = 2 * nr + 1 + dev_offset; 1133 minor_out = 2 * nr + 1 + dev_offset;
1120 } 1134 }
1121 1135
1122 /* allocate space for this pipe */ 1136 /* allocate space for this pipe */
1123 loops[nr]= kmalloc(sizeof(struct vloopback_pipe), GFP_KERNEL); 1137 loops[nr]= kmalloc(sizeof(struct vloopback_pipe), GFP_KERNEL);
1124 1138
1125 if (!loops[nr]) 1139 if (!loops[nr])
1126 return -ENOMEM; 1140 return -ENOMEM;
1127 /* set up a new video device plus our private area */ 1141 /* set up a new video device plus our private area */
1128 loops[nr]->vloopin = video_device_alloc(); 1142 loops[nr]->vloopin = video_device_alloc();
1129 1143
1130 if (loops[nr]->vloopin == NULL) 1144 if (loops[nr]->vloopin == NULL)
1131 return -ENOMEM; 1145 return -ENOMEM;
1132 *loops[nr]->vloopin = vloopback_template; 1146 *loops[nr]->vloopin = vloopback_template;
1133 loops[nr]->vloopin->priv = kmalloc(sizeof(struct vloopback_private), 1147 loops[nr]->vloopin->priv = kmalloc(sizeof(struct vloopback_private),
1134 GFP_KERNEL); 1148 GFP_KERNEL);
1135 if (loops[nr]->vloopin->priv == NULL) { 1149 if (loops[nr]->vloopin->priv == NULL) {
1136 kfree(loops[nr]->vloopin); 1150 kfree(loops[nr]->vloopin);
1137 return -ENOMEM; 1151 return -ENOMEM;
1138 } 1152 }
1139 /* repeat for the output device */ 1153 /* repeat for the output device */
1140 loops[nr]->vloopout = video_device_alloc(); 1154 loops[nr]->vloopout = video_device_alloc();
1141 1155
1142 if (loops[nr]->vloopout == NULL) { 1156 if (loops[nr]->vloopout == NULL) {
1143 kfree(loops[nr]->vloopin->priv); 1157 kfree(loops[nr]->vloopin->priv);
1144 kfree(loops[nr]->vloopin); 1158 kfree(loops[nr]->vloopin);
1145 return -ENOMEM; 1159 return -ENOMEM;
1146 } 1160 }
1147 *loops[nr]->vloopout = vloopback_template; 1161 *loops[nr]->vloopout = vloopback_template;
1148 loops[nr]->vloopout->priv = kmalloc(sizeof(struct vloopback_private), 1162 loops[nr]->vloopout->priv = kmalloc(sizeof(struct vloopback_private),
1149 GFP_KERNEL); 1163 GFP_KERNEL);
1150 1164
1151 if (loops[nr]->vloopout->priv == NULL) { 1165 if (loops[nr]->vloopout->priv == NULL) {
1152 kfree(loops[nr]->vloopin->priv); 1166 kfree(loops[nr]->vloopin->priv);
1153 kfree(loops[nr]->vloopin); 1167 kfree(loops[nr]->vloopin);
1154 kfree(loops[nr]->vloopout); 1168 kfree(loops[nr]->vloopout);
1155 return -ENOMEM; 1169 return -ENOMEM;
1156 } 1170 }
1157 1171
1158 ((priv_ptr)loops[nr]->vloopin->priv)->pipenr = nr; 1172 ((priv_ptr)loops[nr]->vloopin->priv)->pipenr = nr;
1159 ((priv_ptr)loops[nr]->vloopout->priv)->pipenr = nr; 1173 ((priv_ptr)loops[nr]->vloopout->priv)->pipenr = nr;
1160 loops[nr]->invalid_ioctl = 0; /* tibit */ 1174 loops[nr]->invalid_ioctl = 0; /* tibit */
1161 loops[nr]->buffer = NULL; 1175 loops[nr]->buffer = NULL;
1162 loops[nr]->width = 0; 1176 loops[nr]->width = 0;
1163 loops[nr]->height = 0; 1177 loops[nr]->height = 0;
1164 loops[nr]->palette = 0; 1178 loops[nr]->palette = 0;
1165 loops[nr]->frameswrite = 0; 1179 loops[nr]->frameswrite = 0;
1166 loops[nr]->framesread = 0; 1180 loops[nr]->framesread = 0;
1167 loops[nr]->framesdumped = 0; 1181 loops[nr]->framesdumped = 0;
1168 loops[nr]->wopen = 0; 1182 loops[nr]->wopen = 0;
1169 loops[nr]->ropen = 0; 1183 loops[nr]->ropen = 0;
1170 loops[nr]->frame = 0; 1184 loops[nr]->frame = 0;
1171 1185
1172 ((priv_ptr)loops[nr]->vloopin->priv)->in = 1; 1186 ((priv_ptr)loops[nr]->vloopin->priv)->in = 1;
1173 ((priv_ptr)loops[nr]->vloopout->priv)->in = 0; 1187 ((priv_ptr)loops[nr]->vloopout->priv)->in = 0;
1174 sprintf(loops[nr]->vloopin->name, "Video loopback %d input", nr); 1188 sprintf(loops[nr]->vloopin->name, "Video loopback %d input", nr);
1175 sprintf(loops[nr]->vloopout->name, "Video loopback %d output", nr); 1189 sprintf(loops[nr]->vloopout->name, "Video loopback %d output", nr);
1176 1190
1177 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,27) 1191 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,27)
1178 loops[nr]->vloopin->type = 0; 1192 loops[nr]->vloopin->type = 0;
1179 loops[nr]->vloopout->type = VID_TYPE_CAPTURE; 1193 loops[nr]->vloopout->type = VID_TYPE_CAPTURE;
1180 #endif 1194 #endif
1181 loops[nr]->vloopout->minor = minor_out; 1195 loops[nr]->vloopout->minor = minor_out;
1182 loops[nr]->vloopin->minor = minor_in; 1196 loops[nr]->vloopin->minor = minor_in;
1183 1197
1184 init_waitqueue_head(&loops[nr]->wait); 1198 init_waitqueue_head(&loops[nr]->wait);
1185 init_MUTEX(&loops[nr]->lock); 1199 init_MUTEX(&loops[nr]->lock);
1186 1200
1187 ret = video_register_device(loops[nr]->vloopin, VFL_TYPE_GRABBER, minor_in); 1201 ret = video_register_device(loops[nr]->vloopin, VFL_TYPE_GRABBER, minor_in);
1188 1202
1189 if ((ret == -1 ) || ( ret == -23 )) { 1203 if ((ret == -1 ) || ( ret == -23 )) {
1190 info("error registering device %s", loops[nr]->vloopin->name); 1204 info("error registering device %s", loops[nr]->vloopin->name);
1191 kfree(loops[nr]->vloopin->priv); 1205 kfree(loops[nr]->vloopin->priv);
1192 kfree(loops[nr]->vloopin); 1206 kfree(loops[nr]->vloopin);
1193 kfree(loops[nr]->vloopout->priv); 1207 kfree(loops[nr]->vloopout->priv);
1194 kfree(loops[nr]->vloopout); 1208 kfree(loops[nr]->vloopout);
1195 kfree(loops[nr]); 1209 kfree(loops[nr]);
1196 loops[nr] = NULL; 1210 loops[nr] = NULL;
1197 return ret; 1211 return ret;
1198 } 1212 }
1199 1213
1200 ret = video_register_device(loops[nr]->vloopout, VFL_TYPE_GRABBER, minor_out); 1214 ret = video_register_device(loops[nr]->vloopout, VFL_TYPE_GRABBER, minor_out);
1201 1215
1202 if ((ret ==-1) || (ret == -23)) { 1216 if ((ret ==-1) || (ret == -23)) {
1203 info("error registering device %s", loops[nr]->vloopout->name); 1217 info("error registering device %s", loops[nr]->vloopout->name);
1204 kfree(loops[nr]->vloopin->priv); 1218 kfree(loops[nr]->vloopin->priv);
1205 video_unregister_device(loops[nr]->vloopin); 1219 video_unregister_device(loops[nr]->vloopin);
1206 kfree(loops[nr]->vloopout->priv); 1220 kfree(loops[nr]->vloopout->priv);
1207 kfree(loops[nr]->vloopout); 1221 kfree(loops[nr]->vloopout);
1208 kfree(loops[nr]); 1222 kfree(loops[nr]);
1209 loops[nr] = NULL; 1223 loops[nr] = NULL;
1210 return ret; 1224 return ret;
1211 } 1225 }
1212 1226
1213 loops[nr]->ioctldata = kmalloc(1024, GFP_KERNEL); 1227 loops[nr]->ioctldata = kmalloc(1024, GFP_KERNEL);
1214 loops[nr]->ioctlretdata = kmalloc(1024, GFP_KERNEL); 1228 loops[nr]->ioctlretdata = kmalloc(1024, GFP_KERNEL);
1215 return 0; 1229 return 0;
1216 } 1230 }
1217 1231
1218 1232
1219 /**************************************************************************** 1233 /****************************************************************************
1220 * init stuff 1234 * init stuff
1221 ****************************************************************************/ 1235 ****************************************************************************/
1222 1236
1223 1237
1224 MODULE_AUTHOR("J.B. Vreeken (pe1rxq@amsat.org)"); 1238 MODULE_AUTHOR("J.B. Vreeken (pe1rxq@amsat.org)");
1225 MODULE_DESCRIPTION("Video4linux loopback device."); 1239 MODULE_DESCRIPTION("Video4linux loopback device.");
1228 module_param(pipes, int, 000); 1242 module_param(pipes, int, 000);
1229 #else 1243 #else
1230 MODULE_PARM(pipes, "i"); 1244 MODULE_PARM(pipes, "i");
1231 #endif 1245 #endif
1232 1246
1233 MODULE_PARM_DESC(pipes, "Nr of pipes to create (each pipe uses two video devices)"); 1247 MODULE_PARM_DESC(pipes, " Nr of pipes to create (each pipe uses two video devices)");
1234 1248
1235 #if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0) 1249 #if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)
1236 module_param(spares, int, 000); 1250 module_param(spares, int, 000);
1237 #else 1251 #else
1238 MODULE_PARM(spares, "i"); 1252 MODULE_PARM(spares, "i");
1239 #endif 1253 #endif
1240 1254
1241 MODULE_PARM_DESC(spares, "Nr of spare pipes that should be created"); 1255 MODULE_PARM_DESC(spares, " Nr of spare pipes that should be created");
1256
1257 #if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)
1258 module_param(num_buffers, int, 000);
1259 #else
1260 MODULE_PARM(num_buffers, "i");
1261 #endif
1262
1263 MODULE_PARM_DESC(num_buffers, " Prefered numbers of internal buffers to map (default 2)");
1264
1242 1265
1243 #if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0) 1266 #if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)
1244 module_param(dev_offset, int, 000); 1267 module_param(dev_offset, int, 000);
1245 #else 1268 #else
1246 MODULE_PARM(dev_offset_param, "i"); 1269 MODULE_PARM(dev_offset_param, "i");
1247 #endif 1270 #endif
1248 1271
1249 MODULE_PARM_DESC(dev_offset, "Prefered offset for video device numbers"); 1272 MODULE_PARM_DESC(dev_offset, " Prefered offset for video device numbers");
1250 1273
1251 1274
1252 #if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0) 1275 #if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)
1253 module_param(debug, int, 000); 1276 module_param(debug, int, 000);
1254 #else 1277 #else
1255 MODULE_PARM(debug_param, "i"); 1278 MODULE_PARM(debug_param, "i");
1256 #endif 1279 #endif
1257 1280
1258 MODULE_PARM_DESC(debug, "Enable module debug level 0-3 (by default 0)"); 1281 MODULE_PARM_DESC(debug, " Enable module debug level 0-3 (by default 0)");
1259 1282
1260 MODULE_LICENSE("GPL"); 1283 MODULE_LICENSE("GPL");
1261 MODULE_VERSION( VLOOPBACK_VERSION ); 1284 MODULE_VERSION( VLOOPBACK_VERSION );
1262 1285
1263 static int __init vloopback_init(void) 1286 static int __init vloopback_init(void)
1264 { 1287 {
1265 int i,ret; 1288 int i, ret;
1266 1289
1267 info("video4linux loopback driver v"VLOOPBACK_VERSION); 1290 info("video4linux loopback driver v"VLOOPBACK_VERSION);
1268 1291
1269 if (pipes == -1) 1292 if (pipes == -1)
1270 pipes = 1; 1293 pipes = 1;
1271 1294
1272 if (pipes > MAX_PIPES) { 1295 if (pipes > MAX_PIPES) {
1273 pipes = MAX_PIPES; 1296 pipes = MAX_PIPES;
1274 info("Nr of pipes is limited to: %d", MAX_PIPES); 1297 info("Nr of pipes is limited to: %d", MAX_PIPES);
1275 } 1298 }
1276 1299
1277 for (i = 0; i < pipes; i++) { 1300 if (num_buffers < N_BUFFS) {
1278 1301 num_buffers = N_BUFFS;
1279 ret = create_pipe(i); 1302 info("Nr of buffer set to default value %d", N_BUFFS);
1280 1303 }
1281 if (ret == 0) { 1304
1282 info("Loopback %d registered, input: video%d," 1305 for (i = 0; i < pipes; i++) {
1283 " output: video%d", 1306
1284 i, loops[i]->vloopin->minor, 1307 ret = create_pipe(i);
1285 loops[i]->vloopout->minor); 1308
1286 nr_o_pipes = i + 1; 1309 if (ret == 0) {
1287 } else { 1310 info("Loopback %d registered, input: video%d,"
1288 return ret; 1311 " output: video%d",
1289 } 1312 i, loops[i]->vloopin->minor,
1290 } 1313 loops[i]->vloopout->minor);
1291 return 0; 1314 info("Loopback %d , Using %d buffers", i, num_buffers);
1315 nr_o_pipes = i + 1;
1316 } else {
1317 return ret;
1318 }
1319 }
1320 return 0;
1292 } 1321 }
1293 1322
1294 static void __exit cleanup_vloopback_module(void) 1323 static void __exit cleanup_vloopback_module(void)
1295 { 1324 {
1296 int i; 1325 int i;
1297 1326
1298 info("Unregistering video4linux loopback devices"); 1327 info("Unregistering video4linux loopback devices");
1299 1328
1300 for (i = 0; i < nr_o_pipes; i++) { 1329 for (i = 0; i < nr_o_pipes; i++) {
1301 if (loops[i]) { 1330 if (loops[i]) {
1302 kfree(loops[i]->vloopin->priv); 1331 kfree(loops[i]->vloopin->priv);
1303 video_unregister_device(loops[i]->vloopin); 1332 video_unregister_device(loops[i]->vloopin);
1304 kfree(loops[i]->vloopout->priv); 1333 kfree(loops[i]->vloopout->priv);
1305 video_unregister_device(loops[i]->vloopout); 1334 video_unregister_device(loops[i]->vloopout);
1306 1335
1307 if (loops[i]->buffer) 1336 if (loops[i]->buffer)
1308 rvfree(loops[i]->buffer, loops[i]->buflength * N_BUFFS); 1337 rvfree(loops[i]->buffer, loops[i]->buflength * num_buffers);
1309 1338
1310 kfree(loops[i]->ioctldata); 1339 kfree(loops[i]->ioctldata);
1311 kfree(loops[i]->ioctlretdata); 1340 kfree(loops[i]->ioctlretdata);
1312 kfree(loops[i]); 1341 kfree(loops[i]);
1313 } 1342 }
1314 } 1343 }
1315 } 1344 }
1316 1345
1317 module_init(vloopback_init); 1346 module_init(vloopback_init);
1318 module_exit(cleanup_vloopback_module); 1347 module_exit(cleanup_vloopback_module);