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); |
