annotate vloopback.c @ 3:90455db7fda4

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