Mercurial > vloopback
comparison vloopback.c @ 16:2dbe2489381e
updated to 2.6.32
author | Yoshiki Yazawa <yaz@honeyplanet.jp> |
---|---|
date | Fri, 06 Nov 2009 21:57:18 +0900 |
parents | 1011e450be45 |
children | 5afb0aa410ec |
comparison
equal
deleted
inserted
replaced
15:1011e450be45 | 16:2dbe2489381e |
---|---|
47 * released 0.83 | 47 * released 0.83 |
48 * 31.01.01 (J Vreeken) Removed need for 'struct ioctl', use _IOC_SIZE() and | 48 * 31.01.01 (J Vreeken) Removed need for 'struct ioctl', use _IOC_SIZE() and |
49 * IOC_IN instead. | 49 * IOC_IN instead. |
50 * Change the ioctlnr passing to 'unsigned long int' | 50 * Change the ioctlnr passing to 'unsigned long int' |
51 * Instead of just one byte. | 51 * Instead of just one byte. |
52 * THIS BREAKS COMPATIBILITY WITH PREVIOUS VERSIONS!!! | 52 * THIS BREAKS COMPATIBILITY WITH PREVIOUS VERSIONS!!! |
53 * 29.06.01 (J Vreeken) Added dev_offset module option | 53 * 29.06.01 (J Vreeken) Added dev_offset module option |
54 * Made vloopback_template sane | 54 * Made vloopback_template sane |
55 * Added double buffering support | 55 * Added double buffering support |
56 * Made vloopback less verbose | 56 * Made vloopback less verbose |
57 * 20.11.01 (tibit) Made dev_offset option sane | 57 * 20.11.01 (tibit) Made dev_offset option sane |
58 * "Fixed" zerocopy mode by defining the ioctl | 58 * "Fixed" zerocopy mode by defining the ioctl |
59 * VIDIOCSINVALID. An application which provides data | 59 * VIDIOCSINVALID. An application which provides data |
60 * has to issue it when it encounters an error in | 60 * has to issue it when it encounters an error in |
61 * ioctl processing. See dummy.c for examples. | 61 * ioctl processing. See dummy.c for examples. |
62 * 26.11.03 (Kenneth Lavrsen) | 62 * 26.11.03 (Kenneth Lavrsen) |
63 * released 0.91 | 63 * released 0.91 |
77 * For versions < 2.5, I updated the routines to be | 77 * For versions < 2.5, I updated the routines to be |
78 * closer to several other drivers. | 78 * closer to several other drivers. |
79 * | 79 * |
80 * 04.02.05 (Angel Carpintero) | 80 * 04.02.05 (Angel Carpintero) |
81 * Fixed version number to 0.93-pre1. | 81 * Fixed version number to 0.93-pre1. |
82 * Fixed warning for interruptible_sleep_on() deprecated and added | 82 * Fixed warning for interruptible_sleep_on() deprecated and added |
83 * wait_event_interruptible compatible with 2.6.x and 2.7. | 83 * wait_event_interruptible compatible with 2.6.x and 2.7. |
84 * Fixed memory manager for kernel version > 2.6.9. | 84 * Fixed memory manager for kernel version > 2.6.9. |
85 * | 85 * |
86 * 07.02.05 (Kenneth Lavrsen) | 86 * 07.02.05 (Kenneth Lavrsen) |
87 * Changed version to 0.94. | 87 * Changed version to 0.94. |
89 * | 89 * |
90 * 20.02.05 (W Brack) | 90 * 20.02.05 (W Brack) |
91 * Fixed error with wait_event_interruptible. | 91 * Fixed error with wait_event_interruptible. |
92 * Fixed crash when pipe source was stopped before dest. | 92 * Fixed crash when pipe source was stopped before dest. |
93 * | 93 * |
94 * 20.02.05 (Angel Carpintero) | 94 * 20.02.05 (Angel Carpintero) |
95 * Added install and uninstall in Makefile. | 95 * Added install and uninstall in Makefile. |
96 * | 96 * |
97 * | 97 * |
98 * 25.04.05 (Angel Carpintero) | 98 * 25.04.05 (Angel Carpintero) |
99 * Included Samuel Audet's patch, it checks if the input is already | 99 * Included Samuel Audet's patch, it checks if the input is already |
100 * opened in write mode. | 100 * opened in write mode. |
101 * | 101 * |
102 * 02.05.05 (Kenneth Lavrsen) | 102 * 02.05.05 (Kenneth Lavrsen) |
103 * Released 0.95-snap2 formerly as 0.95 | 103 * Released 0.95-snap2 formerly as 0.95 |
104 * | 104 * |
105 * 10.05.05 (Angel Carpintero) | 105 * 10.05.05 (Angel Carpintero) |
106 * Added MODULE_VERSION(), fixed create_pipes when video_register_device() returns | 106 * Added MODULE_VERSION(), fixed create_pipes when video_register_device() returns |
107 * -ENFILE . | 107 * -ENFILE . |
108 * Fix warnings about checking return value from copy_to_user() and copy_from_user() functions. | 108 * Fix warnings about checking return value from copy_to_user() and copy_from_user() functions. |
109 * | 109 * |
110 * 14.11.05 (Angel Carpintero) | 110 * 14.11.05 (Angel Carpintero) |
111 * Added <linux/version.h> that includes LINUX_VERSION_CODE and KERNEL_VERSION to fix | 111 * Added <linux/version.h> that includes LINUX_VERSION_CODE and KERNEL_VERSION to fix |
112 * compilation agains kernel 2.6.14 , change version to 0.97-snap1 | 112 * compilation agains kernel 2.6.14 , change version to 0.97-snap1 |
113 * | 113 * |
114 * 19.12.05 (Angel Carpintero) | 114 * 19.12.05 (Angel Carpintero) |
115 * Added to example option to choose between rgb24 or yuv420p palettes. | 115 * Added to example option to choose between rgb24 or yuv420p palettes. |
116 * | 116 * |
117 * 31.12.05 (Angel Carpintero) | 117 * 31.12.05 (Angel Carpintero) |
118 * Fixed examples, remove perror calls and add support to dummy.c for sysfs. | 118 * Fixed examples, remove perror calls and add support to dummy.c for sysfs. |
119 * | 119 * |
120 * 04.06.06 (Angel Carpintero) | 120 * 04.06.06 (Angel Carpintero) |
121 * Add module_param() for kernel > 2.5 because MODULE_PARAM() macro is obsolete. | 121 * Add module_param() for kernel > 2.5 because MODULE_PARAM() macro is obsolete. |
122 * | 122 * |
123 * 17.06.06 (Angel Carpintero) | 123 * 17.06.06 (Angel Carpintero) |
124 * Release version 1.0 with some fixes and code clean up. Added a Jack Bates contribution | 124 * Release version 1.0 with some fixes and code clean up. Added a Jack Bates contribution |
130 * | 130 * |
131 * 02.11.06 (Angel Carpintero) | 131 * 02.11.06 (Angel Carpintero) |
132 * Make compatible with new kernel stable version 2.6.18, Many functions and declarations has | 132 * Make compatible with new kernel stable version 2.6.18, Many functions and declarations has |
133 * been moved to media/v42l-dev.h and remove from videodev.h/videodev2.h | 133 * been moved to media/v42l-dev.h and remove from videodev.h/videodev2.h |
134 * | 134 * |
135 * 18.01.07 (Angel Carpintero) | 135 * 18.01.07 (Angel Carpintero) |
136 * Change -ENOIOCTLCMD by more appropiate error -ENOTTY. | 136 * Change -ENOIOCTLCMD by more appropiate error -ENOTTY. |
137 * | 137 * |
138 * 18.05.08 (Angel Carpintero) | 138 * 18.05.08 (Angel Carpintero) |
139 * Release 1.1-rc1 as 1.1 stable working with 2.6.24 | 139 * Release 1.1-rc1 as 1.1 stable working with 2.6.24 |
140 * | 140 * |
141 * 17.08.08 (Angel Carpintero) | 141 * 17.08.08 (Angel Carpintero) |
142 * kill_proc() deprecated ,pid API changed , type and owner not available in | 142 * kill_proc() deprecated ,pid API changed , type and owner not available in |
143 * video_device struct, added param debug. | 143 * video_device struct, added param debug. |
144 * | 144 * |
145 * 24.08.08 (Angel Carpintero) | 145 * 24.08.08 (Angel Carpintero) |
146 * Added compat_iotcl32 init in fopsl, replace tabs by 4 spaces in source code, | 146 * Added compat_iotcl32 init in fopsl, replace tabs by 4 spaces in source code, |
147 * add number of buffers as module param. | 147 * add number of buffers as module param. |
148 * | 148 * |
149 * 13.10.08 (Stephan Berberig & Angel Carpintero) | 149 * 13.10.08 (Stephan Berberig & Angel Carpintero) |
150 * Release to work on 2.6.27 , allow v4l_compat_ioctl32 work in 2.6.27 and a little cleanup | 150 * Release to work on 2.6.27 , allow v4l_compat_ioctl32 work in 2.6.27 and a little cleanup |
151 * in Makefile. | 151 * in Makefile. |
152 * | 152 * |
153 * 22.12.08 (Angel Carpintero) | 153 * 22.12.08 (Angel Carpintero) |
154 * Allow build with kernel 2.6.28 and 2.6.27.git ( struct video_dev has not priv member anymore). | 154 * Allow build with kernel 2.6.28 and 2.6.27.git ( struct video_dev has not priv member anymore). |
155 * | |
156 * 17.05.09 (Peter Holik) | |
157 * Patch to allow work with kernel 2.6.29 | |
158 * | |
159 * 05.08.09 (Angel Carpintero) | |
160 * Allow to compile with kernel 2.6.30.* | |
161 * | |
162 * 11.09.09 (Angel Carpintero) | |
163 * Allow to compile with kernel 2.6.31 | |
164 */ | 155 */ |
165 | 156 |
166 | 157 |
167 #define VLOOPBACK_VERSION "1.3-trunk" | 158 #define VLOOPBACK_VERSION "1.4" |
168 | 159 |
169 /* Include files common to 2.4 and 2.6 versions */ | 160 /* Include files common to 2.4 and 2.6 versions */ |
170 #include <linux/version.h> /* >= 2.6.14 LINUX_VERSION_CODE */ | 161 #include <linux/version.h> /* >= 2.6.14 LINUX_VERSION_CODE */ |
171 #include <linux/errno.h> | 162 #include <linux/errno.h> |
172 #include <linux/kernel.h> | 163 #include <linux/kernel.h> |
173 #include <linux/module.h> | 164 #include <linux/module.h> |
174 #include <linux/pagemap.h> | 165 #include <linux/pagemap.h> |
175 | 166 |
176 #ifndef CONFIG_VIDEO_V4L1_COMPAT | 167 #ifndef CONFIG_VIDEO_V4L1_COMPAT |
177 #error "need CONFIG_VIDEO_V4L1_COMPAT" | 168 #error "need CONFIG_VIDEO_V4L1_COMPAT" |
178 #endif | 169 #endif |
179 | 170 |
180 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,18) | 171 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,18) |
181 #include <media/v4l2-common.h> | 172 #include <media/v4l2-common.h> |
182 #endif | |
183 | |
184 /* v4l_compat_ioctl32 */ | |
185 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27) | |
186 #ifdef __KERNEL__ | |
187 #undef __KERNEL__ | |
188 #endif | |
189 #include <media/v4l2-ioctl.h> | |
190 #endif | |
191 | |
192 #if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,27) | |
193 #define vd_private_data dev.driver_data | |
194 #ifndef __KERNEL__ | |
195 #define __KERNEL__ | |
196 #endif | |
197 #else | |
198 #define vd_private_data priv | |
199 #endif | 173 #endif |
200 | 174 |
201 #include <linux/videodev.h> | 175 #include <linux/videodev.h> |
202 #include <linux/vmalloc.h> | 176 #include <linux/vmalloc.h> |
203 #include <linux/wait.h> | 177 #include <linux/wait.h> |
204 | 178 |
179 /* v4l_compat_ioctl32 */ | |
180 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27) | |
181 #include <media/v4l2-ioctl.h> | |
182 #endif | |
183 | |
184 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,27) | |
185 #define video_get_drvdata(dev) (priv) | |
186 #define video_set_drvdata(dev, data) (priv = (data)) | |
187 #elseif LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,31) | |
188 #define video_get_drvdata(dev) ((dev).driver_data) | |
189 #define video_set_drvdata(dev, data) ((dev) = (data)) | |
190 #endif | |
205 | 191 |
206 /* Include files which are unique to versions */ | 192 /* Include files which are unique to versions */ |
207 #if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0) | 193 #if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0) |
208 #include <asm/ioctl.h> | 194 #include <asm/ioctl.h> |
209 #include <asm/page.h> | 195 #include <asm/page.h> |
210 #include <asm/pgtable.h> | 196 #include <asm/pgtable.h> |
211 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,10) | 197 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,10) |
212 #ifndef remap_pfn_range | 198 #ifndef remap_pfn_range |
213 #define remap_pfn_range(a,b,c,d,e) \ | 199 #define remap_pfn_range(a,b,c,d,e) \ |
214 remap_page_range((a),(b),(c)<<PAGE_SHIFT,(d),(e)) | 200 remap_page_range((a),(b),(c)<<PAGE_SHIFT,(d),(e)) |
224 #include <linux/mm.h> | 210 #include <linux/mm.h> |
225 #include <linux/slab.h> | 211 #include <linux/slab.h> |
226 #include <linux/wrapper.h> | 212 #include <linux/wrapper.h> |
227 #include <asm/io.h> | 213 #include <asm/io.h> |
228 #endif | 214 #endif |
229 | 215 |
230 #define VIDIOCSINVALID _IO('v',BASE_VIDIOCPRIVATE+1) | 216 #define VIDIOCSINVALID _IO('v',BASE_VIDIOCPRIVATE+1) |
231 | 217 |
232 #define verbose(format, arg...) if (printk_ratelimit()) \ | 218 #define verbose(format, arg...) if (printk_ratelimit()) \ |
233 printk(KERN_INFO "[%s] %s: " format "\n" "", \ | 219 printk(KERN_INFO "[%s] %s: " format "\n" "", \ |
234 __FUNCTION__, __FILE__, ## arg) | 220 __FUNCTION__, __FILE__, ## arg) |
235 | 221 |
236 #define info(format, arg...) if (printk_ratelimit()) \ | 222 #define info(format, arg...) if (printk_ratelimit()) \ |
237 printk(KERN_INFO "[%s] : " format "\n" "", \ | 223 printk(KERN_INFO "[%s] : " format "\n" "", \ |
238 __FUNCTION__, ## arg) | 224 __FUNCTION__, ## arg) |
239 | 225 |
240 #define LOG_NODEBUG 0 | 226 #define LOG_NODEBUG 0 |
241 #define LOG_FUNCTIONS 1 | 227 #define LOG_FUNCTIONS 1 |
242 #define LOG_IOCTL 2 | 228 #define LOG_IOCTL 2 |
243 #define LOG_VERBOSE 3 | 229 #define LOG_VERBOSE 3 |
244 | 230 |
245 struct vloopback_private { | 231 struct vloopback_private { |
262 unsigned int wopen; | 248 unsigned int wopen; |
263 unsigned int ropen; | 249 unsigned int ropen; |
264 struct semaphore lock; | 250 struct semaphore lock; |
265 wait_queue_head_t wait; | 251 wait_queue_head_t wait; |
266 unsigned int frame; | 252 unsigned int frame; |
267 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,27) | 253 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,27) |
268 unsigned int pid; | 254 unsigned int pid; |
269 #else | 255 #else |
270 struct pid *pid; | 256 struct pid *pid; |
271 #endif | 257 #endif |
272 unsigned int zerocopy; | 258 unsigned int zerocopy; |
273 unsigned long int ioctlnr; | 259 unsigned long int ioctlnr; |
274 unsigned int invalid_ioctl; /* 0 .. none invalid; 1 .. invalid */ | 260 unsigned int invalid_ioctl; /* 0 .. none invalid; 1 .. invalid */ |
275 unsigned int ioctllength; | 261 unsigned int ioctllength; |
276 char *ioctldata; | 262 char *ioctldata; |
297 #if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0) | 283 #if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0) |
298 /* Here we want the physical address of the memory. | 284 /* Here we want the physical address of the memory. |
299 * This is used when initializing the contents of the | 285 * This is used when initializing the contents of the |
300 * area and marking the pages as reserved. | 286 * area and marking the pages as reserved. |
301 */ | 287 */ |
302 static inline unsigned long kvirt_to_pa(unsigned long adr) | 288 static inline unsigned long kvirt_to_pa(unsigned long adr) |
303 { | 289 { |
304 unsigned long kva; | 290 unsigned long kva; |
305 | 291 |
306 kva = (unsigned long)page_address(vmalloc_to_page((void *)adr)); | 292 kva = (unsigned long)page_address(vmalloc_to_page((void *)adr)); |
307 kva |= adr & (PAGE_SIZE-1); /* restore the offset */ | 293 kva |= adr & (PAGE_SIZE-1); /* restore the offset */ |
384 #if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0) | 370 #if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0) |
385 fw = loops[nr]->frameswrite; | 371 fw = loops[nr]->frameswrite; |
386 wait_event_interruptible(loops[nr]->wait, fw != loops[nr]->frameswrite); | 372 wait_event_interruptible(loops[nr]->wait, fw != loops[nr]->frameswrite); |
387 #else | 373 #else |
388 interruptible_sleep_on(&loops[nr]->wait); | 374 interruptible_sleep_on(&loops[nr]->wait); |
389 #endif | 375 #endif |
390 if (cmd & IOC_IN) { | 376 if (cmd & IOC_IN) { |
391 if (memcmp (arg, loops[nr]->ioctlretdata, _IOC_SIZE(cmd))) | 377 if (memcmp (arg, loops[nr]->ioctlretdata, _IOC_SIZE(cmd))) |
392 return 1; | 378 return 1; |
393 } else { | 379 } else { |
394 memcpy (arg, loops[nr]->ioctlretdata, _IOC_SIZE(cmd)); | 380 memcpy (arg, loops[nr]->ioctlretdata, _IOC_SIZE(cmd)); |
399 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,29) | 385 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,29) |
400 static int vloopback_open(struct inode *inod, struct file *f) | 386 static int vloopback_open(struct inode *inod, struct file *f) |
401 #else | 387 #else |
402 static int vloopback_open(struct file *f) | 388 static int vloopback_open(struct file *f) |
403 #endif | 389 #endif |
404 { | 390 { |
405 struct video_device *loopdev = video_devdata(f); | 391 struct video_device *loopdev = video_devdata(f); |
406 priv_ptr ptr = (priv_ptr)loopdev->vd_private_data; | 392 priv_ptr ptr = (priv_ptr)video_get_drvdata(loopdev); |
407 //priv_ptr ptr = (priv_ptr)video_get_drvdata(loopdev); | |
408 int nr = ptr->pipenr; | 393 int nr = ptr->pipenr; |
409 | 394 |
410 if (debug > LOG_NODEBUG) | 395 if (debug > LOG_NODEBUG) |
411 info("Video loopback %d", nr); | 396 info("Video loopback %d", nr); |
412 | 397 |
413 /* Only allow a output to be opened if there is someone feeding | 398 /* Only allow a output to be opened if there is someone feeding |
414 * the pipe. | 399 * the pipe. |
415 */ | 400 */ |
416 if (!ptr->in) { | 401 if (!ptr->in) { |
417 if (loops[nr]->buffer == NULL) | 402 if (loops[nr]->buffer == NULL) |
418 return -EINVAL; | 403 return -EINVAL; |
419 | 404 |
420 loops[nr]->framesread = 0; | 405 loops[nr]->framesread = 0; |
421 loops[nr]->ropen = 1; | 406 loops[nr]->ropen = 1; |
422 } else { | 407 } else { |
423 if (loops[nr]->ropen || loops[nr]->wopen) | 408 if (loops[nr]->ropen || loops[nr]->wopen) |
424 return -EBUSY; | 409 return -EBUSY; |
425 | 410 |
426 loops[nr]->framesdumped = 0; | 411 loops[nr]->framesdumped = 0; |
427 loops[nr]->frameswrite = 0; | 412 loops[nr]->frameswrite = 0; |
428 loops[nr]->wopen = 1; | 413 loops[nr]->wopen = 1; |
440 nr_o_pipes++; | 425 nr_o_pipes++; |
441 } | 426 } |
442 } | 427 } |
443 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,27) | 428 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,27) |
444 loops[nr]->pid = current->pid; | 429 loops[nr]->pid = current->pid; |
445 #elif LINUX_VERSION_CODE > KERNEL_VERSION(2,6,30) | 430 #elseif LINUX_VERSION_CODE < KERNEL_VERSION(2,6,31) |
446 loops[nr]->pid = find_pid_ns(current->pid,0); | |
447 #else | |
448 // TODO : Check in stable 2.6.27 | |
449 loops[nr]->pid = task_pid(find_task_by_vpid(current->pid)); | 431 loops[nr]->pid = task_pid(find_task_by_vpid(current->pid)); |
450 //loops[nr]->pid = task_pid(current); | 432 #else |
451 #endif | 433 loops[nr]->pid = task_pid(current); |
434 #endif | |
452 | 435 |
453 if (debug > LOG_NODEBUG) | 436 if (debug > LOG_NODEBUG) |
454 info("Current pid %d", current->pid); | 437 info("Current pid %d", current->pid); |
455 } | 438 } |
456 return 0; | 439 return 0; |
461 #else | 444 #else |
462 static int vloopback_release(struct file *f) | 445 static int vloopback_release(struct file *f) |
463 #endif | 446 #endif |
464 { | 447 { |
465 struct video_device *loopdev = video_devdata(f); | 448 struct video_device *loopdev = video_devdata(f); |
466 priv_ptr ptr = (priv_ptr)loopdev->vd_private_data; | 449 priv_ptr ptr = (priv_ptr)video_get_drvdata(loopdev); |
467 //priv_ptr ptr = (priv_ptr)video_get_drvdata(loopdev); | |
468 int nr = ptr->pipenr; | 450 int nr = ptr->pipenr; |
469 | 451 |
470 if (debug > LOG_NODEBUG) | 452 if (debug > LOG_NODEBUG) |
471 info("Video loopback %d", nr); | 453 info("Video loopback %d", nr); |
472 | 454 |
477 loops[nr]->buffer = NULL; | 459 loops[nr]->buffer = NULL; |
478 } | 460 } |
479 | 461 |
480 up(&loops[nr]->lock); | 462 up(&loops[nr]->lock); |
481 loops[nr]->frameswrite++; | 463 loops[nr]->frameswrite++; |
482 | 464 |
483 if (waitqueue_active(&loops[nr]->wait)) | 465 if (waitqueue_active(&loops[nr]->wait)) |
484 wake_up(&loops[nr]->wait); | 466 wake_up(&loops[nr]->wait); |
485 | 467 |
486 loops[nr]->width = 0; | 468 loops[nr]->width = 0; |
487 loops[nr]->height = 0; | 469 loops[nr]->height = 0; |
504 loops[nr]->ioctllength = 0; | 486 loops[nr]->ioctllength = 0; |
505 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,27) | 487 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,27) |
506 kill_proc(loops[nr]->pid, SIGIO, 1); | 488 kill_proc(loops[nr]->pid, SIGIO, 1); |
507 #else | 489 #else |
508 kill_pid(loops[nr]->pid, SIGIO, 1); | 490 kill_pid(loops[nr]->pid, SIGIO, 1); |
509 #endif | 491 #endif |
510 } | 492 } |
511 } | 493 } |
512 | 494 |
513 return 0; | 495 return 0; |
514 } | 496 } |
515 | 497 |
516 static ssize_t vloopback_write(struct file *f, const char *buf, | 498 static ssize_t vloopback_write(struct file *f, const char *buf, |
517 size_t count, loff_t *offset) | 499 size_t count, loff_t *offset) |
518 { | 500 { |
519 struct video_device *loopdev = video_devdata(f); | 501 struct video_device *loopdev = video_devdata(f); |
520 priv_ptr ptr = (priv_ptr)loopdev->vd_private_data; | 502 priv_ptr ptr = (priv_ptr)video_get_drvdata(loopdev); |
521 //priv_ptr ptr = (priv_ptr)video_get_drvdata(loopdev); | |
522 int nr = ptr->pipenr; | 503 int nr = ptr->pipenr; |
523 unsigned long realcount = count; | 504 unsigned long realcount = count; |
524 | 505 |
525 if (debug > LOG_IOCTL) | 506 if (debug > LOG_IOCTL) |
526 info("Video loopback %d", nr); | 507 info("Video loopback %d", nr); |
528 if (!ptr->in) | 509 if (!ptr->in) |
529 return -EINVAL; | 510 return -EINVAL; |
530 | 511 |
531 if (loops[nr]->zerocopy) | 512 if (loops[nr]->zerocopy) |
532 return -EINVAL; | 513 return -EINVAL; |
533 | 514 |
534 if (loops[nr]->buffer == NULL) | 515 if (loops[nr]->buffer == NULL) |
535 return -EINVAL; | 516 return -EINVAL; |
536 | 517 |
537 /* Anybody want some pictures??? */ | 518 /* Anybody want some pictures??? */ |
538 if (!waitqueue_active(&loops[nr]->wait)) { | 519 if (!waitqueue_active(&loops[nr]->wait)) { |
539 loops[nr]->framesdumped++; | 520 loops[nr]->framesdumped++; |
540 return realcount; | 521 return realcount; |
541 } | 522 } |
542 | 523 |
543 down(&loops[nr]->lock); | 524 down(&loops[nr]->lock); |
544 if (!loops[nr]->buffer) { | 525 if (!loops[nr]->buffer) { |
545 up(&loops[nr]->lock); | 526 up(&loops[nr]->lock); |
546 return -EINVAL; | 527 return -EINVAL; |
547 } | 528 } |
548 | 529 |
549 if (realcount > loops[nr]->buflength) { | 530 if (realcount > loops[nr]->buflength) { |
550 realcount = loops[nr]->buflength; | 531 realcount = loops[nr]->buflength; |
551 info("Too much data for Video loopback %d ! Only %ld bytes used.", | 532 info("Too much data for Video loopback %d ! Only %ld bytes used.", |
552 nr, realcount); | 533 nr, realcount); |
553 } | 534 } |
554 | 535 |
555 if (copy_from_user(loops[nr]->buffer + loops[nr]->frame * loops[nr]->buflength, | 536 if (copy_from_user(loops[nr]->buffer + loops[nr]->frame * loops[nr]->buflength, |
556 buf, realcount)) | 537 buf, realcount)) |
557 return -EFAULT; | 538 return -EFAULT; |
558 | 539 |
559 loops[nr]->frame = 0; | 540 loops[nr]->frame = 0; |
560 up(&loops[nr]->lock); | 541 up(&loops[nr]->lock); |
561 | 542 |
563 wake_up(&loops[nr]->wait); | 544 wake_up(&loops[nr]->wait); |
564 | 545 |
565 return realcount; | 546 return realcount; |
566 } | 547 } |
567 | 548 |
568 static ssize_t vloopback_read(struct file * f, char * buf, size_t count, | 549 static ssize_t vloopback_read(struct file * f, char * buf, size_t count, |
569 loff_t *offset) | 550 loff_t *offset) |
570 { | 551 { |
571 struct video_device *loopdev = video_devdata(f); | 552 struct video_device *loopdev = video_devdata(f); |
572 priv_ptr ptr = (priv_ptr)loopdev->vd_private_data; | 553 priv_ptr ptr = (priv_ptr)video_get_drvdata(loopdev); |
573 //priv_ptr ptr = (priv_ptr)video_get_drvdata(loopdev); | |
574 int nr = ptr->pipenr; | 554 int nr = ptr->pipenr; |
575 unsigned long realcount = count; | 555 unsigned long realcount = count; |
576 | 556 |
577 if (debug > LOG_IOCTL) | 557 if (debug > LOG_IOCTL) |
578 info("Video loopback %d", nr); | 558 info("Video loopback %d", nr); |
583 realcount = loops[nr]->ioctllength + sizeof(unsigned long int); | 563 realcount = loops[nr]->ioctllength + sizeof(unsigned long int); |
584 | 564 |
585 if (copy_to_user(buf , &loops[nr]->ioctlnr, sizeof(unsigned long int))) | 565 if (copy_to_user(buf , &loops[nr]->ioctlnr, sizeof(unsigned long int))) |
586 return -EFAULT; | 566 return -EFAULT; |
587 | 567 |
588 if (copy_to_user(buf + sizeof(unsigned long int), loops[nr]->ioctldata, | 568 if (copy_to_user(buf + sizeof(unsigned long int), loops[nr]->ioctldata, |
589 realcount - sizeof(unsigned long int))) | 569 realcount - sizeof(unsigned long int))) |
590 return -EFAULT; | 570 return -EFAULT; |
591 | 571 |
592 if (loops[nr]->ioctlnr == 0) | 572 if (loops[nr]->ioctlnr == 0) |
593 loops[nr]->ioctlnr = -1; | 573 loops[nr]->ioctlnr = -1; |
594 | 574 |
595 return realcount; | 575 return realcount; |
596 } else { | 576 } else { |
597 struct video_window vidwin; | 577 struct video_window vidwin; |
598 struct video_mmap vidmmap; | 578 struct video_mmap vidmmap; |
599 struct video_picture vidpic; | 579 struct video_picture vidpic; |
600 | 580 |
601 fake_ioctl(nr, VIDIOCGWIN, &vidwin); | 581 fake_ioctl(nr, VIDIOCGWIN, &vidwin); |
602 fake_ioctl(nr, VIDIOCGPICT, &vidpic); | 582 fake_ioctl(nr, VIDIOCGPICT, &vidpic); |
603 | 583 |
604 vidmmap.height = vidwin.height; | 584 vidmmap.height = vidwin.height; |
605 vidmmap.width = vidwin.width; | 585 vidmmap.width = vidwin.width; |
625 } | 605 } |
626 | 606 |
627 if (!loops[nr]->zerocopy) { | 607 if (!loops[nr]->zerocopy) { |
628 #if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0) | 608 #if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0) |
629 unsigned long fw = loops[nr]->frameswrite; | 609 unsigned long fw = loops[nr]->frameswrite; |
630 | 610 |
631 wait_event_interruptible(loops[nr]->wait, fw != loops[nr]->frameswrite); | 611 wait_event_interruptible(loops[nr]->wait, fw != loops[nr]->frameswrite); |
632 #else | 612 #else |
633 interruptible_sleep_on(&loops[nr]->wait); | 613 interruptible_sleep_on(&loops[nr]->wait); |
634 #endif | 614 #endif |
635 } | 615 } |
650 } | 630 } |
651 | 631 |
652 static int vloopback_mmap(struct file *f, struct vm_area_struct *vma) | 632 static int vloopback_mmap(struct file *f, struct vm_area_struct *vma) |
653 { | 633 { |
654 struct video_device *loopdev = video_devdata(f); | 634 struct video_device *loopdev = video_devdata(f); |
655 priv_ptr ptr = (priv_ptr)loopdev->vd_private_data; | 635 priv_ptr ptr = (priv_ptr)video_get_drvdata(loopdev); |
656 //priv_ptr ptr = (priv_ptr)video_get_drvdata(loopdev); | |
657 int nr = ptr->pipenr; | 636 int nr = ptr->pipenr; |
658 unsigned long start = (unsigned long)vma->vm_start; | 637 unsigned long start = (unsigned long)vma->vm_start; |
659 long size = vma->vm_end - vma->vm_start; | 638 long size = vma->vm_end - vma->vm_start; |
660 unsigned long page, pos; | 639 unsigned long page, pos; |
661 | 640 |
690 if (loops[nr]->buffer == NULL) { | 669 if (loops[nr]->buffer == NULL) { |
691 up(&loops[nr]->lock); | 670 up(&loops[nr]->lock); |
692 return -EINVAL; | 671 return -EINVAL; |
693 } | 672 } |
694 | 673 |
695 if (size > (((num_buffers * loops[nr]->buflength) + PAGE_SIZE - 1) | 674 if (size > (((num_buffers * loops[nr]->buflength) + PAGE_SIZE - 1) |
696 & ~(PAGE_SIZE - 1))) { | 675 & ~(PAGE_SIZE - 1))) { |
697 up(&loops[nr]->lock); | 676 up(&loops[nr]->lock); |
698 return -EINVAL; | 677 return -EINVAL; |
699 } | 678 } |
700 | 679 |
720 | 699 |
721 return 0; | 700 return 0; |
722 } | 701 } |
723 | 702 |
724 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,29) | 703 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,29) |
725 static int vloopback_ioctl(struct inode *inod, struct file *f, unsigned int cmd, | 704 static int vloopback_ioctl(struct inode *inod, struct file *f, unsigned int cmd, |
726 unsigned long arg) | 705 unsigned long arg) |
727 #else | 706 #else |
728 static long vloopback_ioctl(struct file *f, unsigned int cmd, unsigned long arg) | 707 static long vloopback_ioctl(struct file *f, unsigned int cmd, unsigned long arg) |
729 #endif | 708 #endif |
730 { | 709 { |
731 struct video_device *loopdev = video_devdata(f); | 710 struct video_device *loopdev = video_devdata(f); |
732 priv_ptr ptr = (priv_ptr)loopdev->vd_private_data; | 711 priv_ptr ptr = (priv_ptr)video_get_drvdata(loopdev); |
733 //priv_ptr ptr = (priv_ptr)video_get_drvdata(loopdev); | |
734 int nr = ptr->pipenr; | 712 int nr = ptr->pipenr; |
735 int i; | 713 int i; |
736 | 714 |
737 if (debug > LOG_NODEBUG) | 715 if (debug > LOG_NODEBUG) |
738 info("Video loopback %d cmd %u", nr, cmd); | 716 info("Video loopback %d cmd %u", nr, cmd); |
748 return -EFAULT; | 726 return -EFAULT; |
749 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,27) | 727 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,27) |
750 kill_proc(loops[nr]->pid, SIGIO, 1); | 728 kill_proc(loops[nr]->pid, SIGIO, 1); |
751 #else | 729 #else |
752 kill_pid(loops[nr]->pid, SIGIO, 1); | 730 kill_pid(loops[nr]->pid, SIGIO, 1); |
753 #endif | 731 #endif |
754 | 732 |
755 #if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0) | 733 #if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0) |
756 wait_event_interruptible(loops[nr]->wait, loops[nr]->ioctlnr == -1); | 734 wait_event_interruptible(loops[nr]->wait, loops[nr]->ioctlnr == -1); |
757 #else | 735 #else |
758 interruptible_sleep_on(&loops[nr]->wait); | 736 interruptible_sleep_on(&loops[nr]->wait); |
759 #endif | 737 #endif |
760 | 738 |
761 if (loops[nr]->invalid_ioctl) { | 739 if (loops[nr]->invalid_ioctl) { |
762 info ("There was an invalid ioctl in Video loopback %d", nr); | 740 info ("There was an invalid ioctl in Video loopback %d", nr); |
763 loops[nr]->invalid_ioctl = 0; | 741 loops[nr]->invalid_ioctl = 0; |
764 return -ENOTTY; | 742 return -ENOTTY; |
765 } | 743 } |
766 | 744 |
767 if (cmd & IOC_IN && !(cmd & IOC_OUT)) { | 745 if (cmd & IOC_IN && !(cmd & IOC_OUT)) { |
768 //info("DEBUG: vl_ioctl: cmd & IOC_IN 1"); | 746 //info("DEBUG: vl_ioctl: cmd & IOC_IN 1"); |
769 if (memcmp(loops[nr]->ioctlretdata, loops[nr]->ioctldata, _IOC_SIZE(cmd))) | 747 if (memcmp(loops[nr]->ioctlretdata, loops[nr]->ioctldata, _IOC_SIZE(cmd))) |
770 return -EINVAL; | 748 return -EINVAL; |
771 | 749 |
772 //info("DEBUG: vl_ioctl: cmd & IOC_IN 2"); | 750 //info("DEBUG: vl_ioctl: cmd & IOC_IN 2"); |
773 return 0; | 751 return 0; |
774 } else { | 752 } else { |
775 if (copy_to_user((void*)arg, loops[nr]->ioctlretdata, _IOC_SIZE(cmd))) | 753 if (copy_to_user((void*)arg, loops[nr]->ioctlretdata, _IOC_SIZE(cmd))) |
776 return -EFAULT; | 754 return -EFAULT; |
777 //info("DEBUG: vl_ioctl: !(cmd & IOC_IN) 1"); | 755 //info("DEBUG: vl_ioctl: !(cmd & IOC_IN) 1"); |
784 return 0; | 762 return 0; |
785 } | 763 } |
786 | 764 |
787 if (cmd == VIDIOCSINVALID) { | 765 if (cmd == VIDIOCSINVALID) { |
788 loops[nr]->invalid_ioctl = 1; | 766 loops[nr]->invalid_ioctl = 1; |
789 } else if (copy_from_user(loops[nr]->ioctlretdata, | 767 } else if (copy_from_user(loops[nr]->ioctlretdata, |
790 (void*)arg, loops[nr]->ioctllength)) { | 768 (void*)arg, loops[nr]->ioctllength)) { |
791 return -EFAULT; | 769 return -EFAULT; |
792 } | 770 } |
793 | 771 |
794 loops[nr]->ioctlnr = -1; | 772 loops[nr]->ioctlnr = -1; |
945 } | 923 } |
946 /* Set the video overlay window - passes clip list for hardware smarts , chromakey etc */ | 924 /* Set the video overlay window - passes clip list for hardware smarts , chromakey etc */ |
947 case VIDIOCSWIN: | 925 case VIDIOCSWIN: |
948 { | 926 { |
949 struct video_window vw; | 927 struct video_window vw; |
950 | 928 |
951 if (copy_from_user(&vw, (void*)arg, sizeof(vw))) | 929 if (copy_from_user(&vw, (void*)arg, sizeof(vw))) |
952 return -EFAULT; | 930 return -EFAULT; |
953 | 931 |
954 if (vw.flags) | 932 if (vw.flags) |
955 return -EINVAL; | 933 return -EINVAL; |
989 } | 967 } |
990 /* Memory map buffer info */ | 968 /* Memory map buffer info */ |
991 case VIDIOCGMBUF: | 969 case VIDIOCGMBUF: |
992 { | 970 { |
993 struct video_mbuf vm; | 971 struct video_mbuf vm; |
994 | 972 |
995 vm.size = loops[nr]->buflength * num_buffers; | 973 vm.size = loops[nr]->buflength * num_buffers; |
996 vm.frames = num_buffers; | 974 vm.frames = num_buffers; |
997 for (i = 0; i < vm.frames; i++) | 975 for (i = 0; i < vm.frames; i++) |
998 vm.offsets[i] = i * loops[nr]->buflength; | 976 vm.offsets[i] = i * loops[nr]->buflength; |
999 | 977 |
1050 #if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0) | 1028 #if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0) |
1051 fw = loops[nr]->frameswrite; | 1029 fw = loops[nr]->frameswrite; |
1052 wait_event_interruptible(loops[nr]->wait, fw != loops[nr]->frameswrite); | 1030 wait_event_interruptible(loops[nr]->wait, fw != loops[nr]->frameswrite); |
1053 #else | 1031 #else |
1054 interruptible_sleep_on(&loops[nr]->wait); | 1032 interruptible_sleep_on(&loops[nr]->wait); |
1055 #endif | 1033 #endif |
1056 if (!loops[nr]->buffer) /* possibly released during sleep */ | 1034 if (!loops[nr]->buffer) /* possibly released during sleep */ |
1057 return -EINVAL; | 1035 return -EINVAL; |
1058 | 1036 |
1059 loops[nr]->framesread++; | 1037 loops[nr]->framesread++; |
1060 | 1038 |
1062 } | 1040 } |
1063 /* Get attached units */ | 1041 /* Get attached units */ |
1064 case VIDIOCGUNIT: | 1042 case VIDIOCGUNIT: |
1065 { | 1043 { |
1066 struct video_unit vu; | 1044 struct video_unit vu; |
1067 | 1045 |
1068 if (ptr->in) | 1046 if (ptr->in) |
1069 vu.video = loops[nr]->vloopout->minor; | 1047 vu.video = loops[nr]->vloopout->minor; |
1070 else | 1048 else |
1071 vu.video = loops[nr]->vloopin->minor; | 1049 vu.video = loops[nr]->vloopin->minor; |
1072 | 1050 |
1099 int start; | 1077 int start; |
1100 | 1078 |
1101 if (copy_from_user(&start, (void*)arg, sizeof(int))) | 1079 if (copy_from_user(&start, (void*)arg, sizeof(int))) |
1102 return -EFAULT; | 1080 return -EFAULT; |
1103 | 1081 |
1104 if (start) { | 1082 if (start) { |
1105 info ("Video loopback %d Capture started", nr); | 1083 info ("Video loopback %d Capture started", nr); |
1106 } else { | 1084 } else { |
1107 info ("Video loopback %d Capture stopped", nr); | 1085 info ("Video loopback %d Capture stopped", nr); |
1108 } | 1086 } |
1109 | 1087 |
1124 } | 1102 } |
1125 | 1103 |
1126 static unsigned int vloopback_poll(struct file *f, struct poll_table_struct *wait) | 1104 static unsigned int vloopback_poll(struct file *f, struct poll_table_struct *wait) |
1127 { | 1105 { |
1128 struct video_device *loopdev = video_devdata(f); | 1106 struct video_device *loopdev = video_devdata(f); |
1129 priv_ptr ptr = (priv_ptr)loopdev->vd_private_data; | 1107 priv_ptr ptr = (priv_ptr)video_get_drvdata(loopdev); |
1130 //priv_ptr ptr = (priv_ptr)video_get_drvdata(loopdev); | |
1131 int nr = ptr->pipenr; | 1108 int nr = ptr->pipenr; |
1132 | 1109 |
1133 if (debug > LOG_NODEBUG) | 1110 if (debug > LOG_NODEBUG) |
1134 info("Video loopback %d", nr); | 1111 info("Video loopback %d", nr); |
1135 | 1112 |
1168 mmap: vloopback_mmap, | 1145 mmap: vloopback_mmap, |
1169 }; | 1146 }; |
1170 | 1147 |
1171 static struct video_device vloopback_template = | 1148 static struct video_device vloopback_template = |
1172 { | 1149 { |
1173 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,27) | 1150 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,27) |
1174 owner: THIS_MODULE, | 1151 owner: THIS_MODULE, |
1175 type: VID_TYPE_CAPTURE, | 1152 type: VID_TYPE_CAPTURE, |
1176 #endif | 1153 #endif |
1177 minor: -1, | 1154 minor: -1, |
1178 name: "Video Loopback", | 1155 name: "Video Loopback", |
1179 fops: &fileops_template, | 1156 fops: &fileops_template, |
1180 #if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0) | 1157 #if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0) |
1181 release: video_device_release, | 1158 release: video_device_release, |
1182 #endif | 1159 #endif |
1183 }; | 1160 }; |
1184 | 1161 |
1185 static int create_pipe(int nr) | 1162 static int create_pipe(int nr) |
1186 { | 1163 { |
1187 int minor_in, minor_out , ret; | 1164 int minor_in, minor_out , ret; |
1165 priv_ptr ptr; | |
1188 | 1166 |
1189 if (debug > LOG_NODEBUG) | 1167 if (debug > LOG_NODEBUG) |
1190 info("Video loopback %d", nr); | 1168 info("Video loopback %d", nr); |
1191 | 1169 |
1192 if (dev_offset == -1) { | 1170 if (dev_offset == -1) { |
1205 | 1183 |
1206 if (loops[nr]->vloopin == NULL) | 1184 if (loops[nr]->vloopin == NULL) |
1207 return -ENOMEM; | 1185 return -ENOMEM; |
1208 *loops[nr]->vloopin = vloopback_template; | 1186 *loops[nr]->vloopin = vloopback_template; |
1209 | 1187 |
1210 loops[nr]->vloopin->vd_private_data = kmalloc(sizeof(struct vloopback_private), | 1188 ptr = kmalloc(sizeof(struct vloopback_private), GFP_KERNEL); |
1211 GFP_KERNEL); | 1189 if(!ptr) { |
1212 | |
1213 if (loops[nr]->vloopin->vd_private_data == NULL) { | |
1214 kfree(loops[nr]->vloopin); | 1190 kfree(loops[nr]->vloopin); |
1215 return -ENOMEM; | 1191 return -ENOMEM; |
1216 } | 1192 } |
1193 video_set_drvdata(loops[nr]->vloopin, ptr); | |
1217 /* repeat for the output device */ | 1194 /* repeat for the output device */ |
1218 loops[nr]->vloopout = video_device_alloc(); | 1195 loops[nr]->vloopout = video_device_alloc(); |
1219 | 1196 |
1220 if (loops[nr]->vloopout == NULL) { | 1197 if (loops[nr]->vloopout == NULL) { |
1221 kfree(loops[nr]->vloopin->vd_private_data); | 1198 kfree(video_get_drvdata(loops[nr]->vloopin)); |
1222 kfree(loops[nr]->vloopin); | 1199 kfree(loops[nr]->vloopin); |
1200 loops[nr]->vloopin = NULL; | |
1223 return -ENOMEM; | 1201 return -ENOMEM; |
1224 } | 1202 } |
1225 *loops[nr]->vloopout = vloopback_template; | 1203 *loops[nr]->vloopout = vloopback_template; |
1226 loops[nr]->vloopout->vd_private_data = kmalloc(sizeof(struct vloopback_private), | 1204 ptr = kmalloc(sizeof(struct vloopback_private), GFP_KERNEL); |
1227 GFP_KERNEL); | 1205 if(!ptr) { |
1228 | 1206 kfree(video_get_drvdata(loops[nr]->vloopin)); |
1229 if (loops[nr]->vloopout->vd_private_data == NULL) { | |
1230 kfree(loops[nr]->vloopin->vd_private_data); | |
1231 kfree(loops[nr]->vloopin); | 1207 kfree(loops[nr]->vloopin); |
1232 kfree(loops[nr]->vloopout); | 1208 kfree(loops[nr]->vloopout); |
1233 return -ENOMEM; | 1209 return -ENOMEM; |
1234 } | 1210 } |
1235 | 1211 video_set_drvdata(loops[nr]->vloopout, ptr); |
1236 ((priv_ptr)loops[nr]->vloopin->vd_private_data)->pipenr = nr; | 1212 |
1237 ((priv_ptr)loops[nr]->vloopout->vd_private_data)->pipenr = nr; | 1213 ((priv_ptr)video_get_drvdata(loops[nr]->vloopin))->pipenr = nr; |
1214 ((priv_ptr)video_get_drvdata(loops[nr]->vloopout))->pipenr = nr; | |
1215 | |
1238 loops[nr]->invalid_ioctl = 0; /* tibit */ | 1216 loops[nr]->invalid_ioctl = 0; /* tibit */ |
1239 loops[nr]->buffer = NULL; | 1217 loops[nr]->buffer = NULL; |
1240 loops[nr]->width = 0; | 1218 loops[nr]->width = 0; |
1241 loops[nr]->height = 0; | 1219 loops[nr]->height = 0; |
1242 loops[nr]->palette = 0; | 1220 loops[nr]->palette = 0; |
1244 loops[nr]->framesread = 0; | 1222 loops[nr]->framesread = 0; |
1245 loops[nr]->framesdumped = 0; | 1223 loops[nr]->framesdumped = 0; |
1246 loops[nr]->wopen = 0; | 1224 loops[nr]->wopen = 0; |
1247 loops[nr]->ropen = 0; | 1225 loops[nr]->ropen = 0; |
1248 loops[nr]->frame = 0; | 1226 loops[nr]->frame = 0; |
1249 | 1227 |
1250 ((priv_ptr)loops[nr]->vloopin->vd_private_data)->in = 1; | 1228 ((priv_ptr)video_get_drvdata(loops[nr]->vloopin))->in = 1; |
1251 ((priv_ptr)loops[nr]->vloopout->vd_private_data)->in = 0; | 1229 ((priv_ptr)video_get_drvdata(loops[nr]->vloopout))->in = 0; |
1252 sprintf(loops[nr]->vloopin->name, "Video loopback %d input", nr); | 1230 sprintf(loops[nr]->vloopin->name, "Video loopback %d input", nr); |
1253 sprintf(loops[nr]->vloopout->name, "Video loopback %d output", nr); | 1231 sprintf(loops[nr]->vloopout->name, "Video loopback %d output", nr); |
1254 | 1232 |
1255 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,27) | 1233 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,27) |
1256 loops[nr]->vloopin->type = 0; | 1234 loops[nr]->vloopin->type = 0; |
1259 loops[nr]->vloopout->minor = minor_out; | 1237 loops[nr]->vloopout->minor = minor_out; |
1260 loops[nr]->vloopin->minor = minor_in; | 1238 loops[nr]->vloopin->minor = minor_in; |
1261 | 1239 |
1262 init_waitqueue_head(&loops[nr]->wait); | 1240 init_waitqueue_head(&loops[nr]->wait); |
1263 init_MUTEX(&loops[nr]->lock); | 1241 init_MUTEX(&loops[nr]->lock); |
1264 | 1242 |
1265 ret = video_register_device(loops[nr]->vloopin, VFL_TYPE_GRABBER, minor_in); | 1243 ret = video_register_device(loops[nr]->vloopin, VFL_TYPE_GRABBER, minor_in); |
1266 | 1244 |
1267 if ((ret == -1 ) || ( ret == -23 )) { | 1245 if ((ret == -1 ) || ( ret == -23 )) { |
1268 info("error registering device %s", loops[nr]->vloopin->name); | 1246 info("error registering device %s", loops[nr]->vloopin->name); |
1269 kfree(loops[nr]->vloopin->vd_private_data); | 1247 kfree(video_get_drvdata(loops[nr]->vloopin)); |
1270 kfree(loops[nr]->vloopin); | 1248 kfree(loops[nr]->vloopin); |
1271 kfree(loops[nr]->vloopout->vd_private_data); | 1249 kfree(video_get_drvdata(loops[nr]->vloopout)); |
1272 kfree(loops[nr]->vloopout); | 1250 kfree(loops[nr]->vloopout); |
1273 kfree(loops[nr]); | 1251 kfree(loops[nr]); |
1274 loops[nr] = NULL; | 1252 loops[nr] = NULL; |
1275 return ret; | 1253 return ret; |
1276 } | 1254 } |
1277 | 1255 |
1278 ret = video_register_device(loops[nr]->vloopout, VFL_TYPE_GRABBER, minor_out); | 1256 ret = video_register_device(loops[nr]->vloopout, VFL_TYPE_GRABBER, minor_out); |
1279 | 1257 |
1280 if ((ret ==-1) || (ret == -23)) { | 1258 if ((ret ==-1) || (ret == -23)) { |
1281 info("error registering device %s", loops[nr]->vloopout->name); | 1259 info("error registering device %s", loops[nr]->vloopout->name); |
1282 kfree(loops[nr]->vloopin->vd_private_data); | 1260 kfree(video_get_drvdata(loops[nr]->vloopin)); |
1283 video_unregister_device(loops[nr]->vloopin); | 1261 video_unregister_device(loops[nr]->vloopin); |
1284 kfree(loops[nr]->vloopout->vd_private_data); | 1262 kfree(video_get_drvdata(loops[nr]->vloopout)); |
1285 kfree(loops[nr]->vloopout); | 1263 kfree(loops[nr]->vloopout); |
1286 kfree(loops[nr]); | 1264 kfree(loops[nr]); |
1287 loops[nr] = NULL; | 1265 loops[nr] = NULL; |
1288 return ret; | 1266 return ret; |
1289 } | 1267 } |
1290 | 1268 |
1291 loops[nr]->ioctldata = kmalloc(1024, GFP_KERNEL); | 1269 loops[nr]->ioctldata = kmalloc(1024, GFP_KERNEL); |
1292 loops[nr]->ioctlretdata = kmalloc(1024, GFP_KERNEL); | 1270 loops[nr]->ioctlretdata = kmalloc(1024, GFP_KERNEL); |
1293 return 0; | 1271 return 0; |
1294 } | 1272 } |
1295 | 1273 |
1351 { | 1329 { |
1352 int i, ret; | 1330 int i, ret; |
1353 | 1331 |
1354 info("video4linux loopback driver v"VLOOPBACK_VERSION); | 1332 info("video4linux loopback driver v"VLOOPBACK_VERSION); |
1355 | 1333 |
1356 if (pipes == -1) | 1334 if (pipes == -1) |
1357 pipes = 1; | 1335 pipes = 1; |
1358 | 1336 |
1359 if (pipes > MAX_PIPES) { | 1337 if (pipes > MAX_PIPES) { |
1360 pipes = MAX_PIPES; | 1338 pipes = MAX_PIPES; |
1361 info("Nr of pipes is limited to: %d", MAX_PIPES); | 1339 info("Nr of pipes is limited to: %d", MAX_PIPES); |
1365 num_buffers = N_BUFFS; | 1343 num_buffers = N_BUFFS; |
1366 info("Nr of buffer set to default value %d", N_BUFFS); | 1344 info("Nr of buffer set to default value %d", N_BUFFS); |
1367 } | 1345 } |
1368 | 1346 |
1369 for (i = 0; i < pipes; i++) { | 1347 for (i = 0; i < pipes; i++) { |
1370 | 1348 |
1371 ret = create_pipe(i); | 1349 ret = create_pipe(i); |
1372 | 1350 |
1373 if (ret == 0) { | 1351 if (ret == 0) { |
1374 info("Loopback %d registered, input: video%d," | 1352 info("Loopback %d registered, input: /dev/video%d minor %d," |
1375 " output: video%d", | 1353 " output: /dev/video%d minor %d", |
1376 i, loops[i]->vloopin->minor, | 1354 i, loops[i]->vloopin->num, loops[i]->vloopin->minor, |
1377 loops[i]->vloopout->minor); | 1355 loops[i]->vloopout->num, loops[i]->vloopout->minor); |
1378 info("Loopback %d , Using %d buffers", i, num_buffers); | 1356 info("Loopback %d , Using %d buffers", i, num_buffers); |
1379 nr_o_pipes = i + 1; | 1357 nr_o_pipes = i + 1; |
1380 } else { | 1358 } else { |
1381 return ret; | 1359 return ret; |
1382 } | 1360 } |
1390 | 1368 |
1391 info("Unregistering video4linux loopback devices"); | 1369 info("Unregistering video4linux loopback devices"); |
1392 | 1370 |
1393 for (i = 0; i < nr_o_pipes; i++) { | 1371 for (i = 0; i < nr_o_pipes; i++) { |
1394 if (loops[i]) { | 1372 if (loops[i]) { |
1395 kfree(loops[i]->vloopin->vd_private_data); | 1373 kfree(video_get_drvdata(loops[i]->vloopin)); |
1396 video_unregister_device(loops[i]->vloopin); | 1374 video_unregister_device(loops[i]->vloopin); |
1397 kfree(loops[i]->vloopout->vd_private_data); | 1375 kfree(video_get_drvdata(loops[i]->vloopout)); |
1398 video_unregister_device(loops[i]->vloopout); | 1376 video_unregister_device(loops[i]->vloopout); |
1399 | 1377 |
1400 if (loops[i]->buffer) | 1378 if (loops[i]->buffer) |
1401 rvfree(loops[i]->buffer, loops[i]->buflength * num_buffers); | 1379 rvfree(loops[i]->buffer, loops[i]->buflength * num_buffers); |
1402 | 1380 |
1403 kfree(loops[i]->ioctldata); | 1381 kfree(loops[i]->ioctldata); |
1404 kfree(loops[i]->ioctlretdata); | 1382 kfree(loops[i]->ioctlretdata); |
1405 kfree(loops[i]); | 1383 kfree(loops[i]); |
1406 } | 1384 } |
1407 } | 1385 } |
1408 } | 1386 } |
1409 | 1387 |
1410 module_init(vloopback_init); | 1388 module_init(vloopback_init); |
1411 module_exit(cleanup_vloopback_module); | 1389 module_exit(cleanup_vloopback_module); |