aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media
diff options
context:
space:
mode:
authorThierry MERLE <thierry.merle@free.fr>2006-12-04 06:31:24 -0500
committerMauro Carvalho Chehab <mchehab@infradead.org>2006-12-10 06:05:48 -0500
commit40bad67840aa6856cb39a431510a57d940017898 (patch)
tree2ce2b00bf379e7c41fb7ef983537f183108d51d9 /drivers/media
parent3084920b555b3ba73590430b2e03d9167db23e8e (diff)
V4L/DVB (4930): Usbvision_v4l2 : mmap corrected to get all frames
- private ioctls UVIOCSREG/UVIOCGREG translated to the VIDIOC_INT_G_REGISTER/VIDIOC_INT_S_REGISTER - lost frame bug corrected (mmap rework) - reset scratch buffer is no buffer is queued (prevents useless scratch overflow management) Signed-off-by: Thierry MERLE <thierry.merle@free.fr> Signed-off-by: Mauro Carvalho Chehab <mchehab@infradead.org>
Diffstat (limited to 'drivers/media')
-rw-r--r--drivers/media/video/usbvision/usbvision-core.c105
1 files changed, 59 insertions, 46 deletions
diff --git a/drivers/media/video/usbvision/usbvision-core.c b/drivers/media/video/usbvision/usbvision-core.c
index 3833f3fbbdf0..eb8f4ca3a15f 100644
--- a/drivers/media/video/usbvision/usbvision-core.c
+++ b/drivers/media/video/usbvision/usbvision-core.c
@@ -364,8 +364,6 @@
364#endif 364#endif
365 365
366#include "usbvision.h" 366#include "usbvision.h"
367#include "usbvision_ioctl.h"
368
369 367
370#define DRIVER_VERSION "0.9.8.3cvs for Linux kernels 2.4.19-2.4.32 + 2.6.0-2.6.17, compiled at "__DATE__", "__TIME__ 368#define DRIVER_VERSION "0.9.8.3cvs for Linux kernels 2.4.19-2.4.32 + 2.6.0-2.6.17, compiled at "__DATE__", "__TIME__
371#define EMAIL "joerg@heckenbach-aw.de" 369#define EMAIL "joerg@heckenbach-aw.de"
@@ -2320,6 +2318,10 @@ static void usbvision_isocIrq(struct urb *urb, struct pt_regs *regs)
2320 } 2318 }
2321 } 2319 }
2322 } 2320 }
2321 else {
2322 PDEBUG(DBG_IRQ, "received data, but no one needs it");
2323 scratch_reset(usbvision);
2324 }
2323 2325
2324 usbvision->timeInIrq += jiffies - startTime; 2326 usbvision->timeInIrq += jiffies - startTime;
2325 2327
@@ -3901,41 +3903,50 @@ static int usbvision_v4l2_do_ioctl(struct inode *inode, struct file *file,
3901 // if (debug & DBG_IOCTL) v4l_printk_ioctl(cmd); 3903 // if (debug & DBG_IOCTL) v4l_printk_ioctl(cmd);
3902 3904
3903 switch (cmd) { 3905 switch (cmd) {
3904 case UVIOCSREG: 3906
3907#ifdef CONFIG_VIDEO_ADV_DEBUG
3908 /* ioctls to allow direct acces to the NT100x registers */
3909 case VIDIOC_INT_G_REGISTER:
3905 { 3910 {
3906 struct usbvision_reg *usbvision_reg = arg; 3911 struct v4l2_register *reg = arg;
3907 int errCode; 3912 int errCode;
3908 3913
3909 errCode = usbvision_write_reg(usbvision, usbvision_reg->addr, usbvision_reg->value); 3914 if (reg->i2c_id != 0)
3910 3915 return -EINVAL;
3916 /* NT100x has a 8-bit register space */
3917 errCode = usbvision_read_reg(usbvision, reg->reg&0xff);
3911 if (errCode < 0) { 3918 if (errCode < 0) {
3912 err("%s: UVIOCSREG failed: error %d", __FUNCTION__, errCode); 3919 err("%s: VIDIOC_INT_G_REGISTER failed: error %d", __FUNCTION__, errCode);
3913 } 3920 }
3914 else { 3921 else {
3915 PDEBUG(DBG_IOCTL, "UVIOCSREG addr=0x%02X, value=0x%02X", 3922 reg->val=(unsigned char)errCode;
3916 usbvision_reg->addr, usbvision_reg->value); 3923 PDEBUG(DBG_IOCTL, "VIDIOC_INT_G_REGISTER reg=0x%02X, value=0x%02X",
3917 errCode = 0; 3924 (unsigned int)reg->reg, reg->val);
3925 errCode = 0; // No error
3918 } 3926 }
3919 return errCode; 3927 return errCode;
3920 } 3928 }
3921 case UVIOCGREG: 3929 case VIDIOC_INT_S_REGISTER:
3922 { 3930 {
3923 struct usbvision_reg *usbvision_reg = arg; 3931 struct v4l2_register *reg = arg;
3924 int errCode; 3932 int errCode;
3925 3933
3926 errCode = usbvision_read_reg(usbvision, usbvision_reg->addr); 3934 if (reg->i2c_id != 0)
3927 3935 return -EINVAL;
3936 if (!capable(CAP_SYS_ADMIN))
3937 return -EPERM;
3938 errCode = usbvision_write_reg(usbvision, reg->reg&0xff, reg->val);
3928 if (errCode < 0) { 3939 if (errCode < 0) {
3929 err("%s: UVIOCGREG failed: error %d", __FUNCTION__, errCode); 3940 err("%s: VIDIOC_INT_S_REGISTER failed: error %d", __FUNCTION__, errCode);
3930 } 3941 }
3931 else { 3942 else {
3932 usbvision_reg->value=(unsigned char)errCode; 3943 PDEBUG(DBG_IOCTL, "VIDIOC_INT_S_REGISTER reg=0x%02X, value=0x%02X",
3933 PDEBUG(DBG_IOCTL, "UVIOCGREG addr=0x%02X, value=0x%02X", 3944 (unsigned int)reg->reg, reg->val);
3934 usbvision_reg->addr, usbvision_reg->value); 3945 errCode = 0;
3935 errCode = 0; // No error
3936 } 3946 }
3937 return errCode; 3947 return 0;
3938 } 3948 }
3949#endif
3939 case VIDIOC_QUERYCAP: 3950 case VIDIOC_QUERYCAP:
3940 { 3951 {
3941 struct v4l2_capability *vc=arg; 3952 struct v4l2_capability *vc=arg;
@@ -4232,12 +4243,9 @@ static int usbvision_v4l2_do_ioctl(struct inode *inode, struct file *file,
4232 if(frame->grabstate == FrameState_Unused) 4243 if(frame->grabstate == FrameState_Unused)
4233 vb->flags |= V4L2_BUF_FLAG_MAPPED; 4244 vb->flags |= V4L2_BUF_FLAG_MAPPED;
4234 vb->memory = V4L2_MEMORY_MMAP; 4245 vb->memory = V4L2_MEMORY_MMAP;
4235 if(vb->index == 0) { 4246
4236 vb->m.offset = 0; 4247 vb->m.offset = vb->index*MAX_FRAME_SIZE;
4237 } 4248
4238 else {
4239 vb->m.offset = MAX_FRAME_SIZE;
4240 }
4241 vb->memory = V4L2_MEMORY_MMAP; 4249 vb->memory = V4L2_MEMORY_MMAP;
4242 vb->field = V4L2_FIELD_NONE; 4250 vb->field = V4L2_FIELD_NONE;
4243 vb->length = MAX_FRAME_SIZE; 4251 vb->length = MAX_FRAME_SIZE;
@@ -4695,40 +4703,45 @@ static ssize_t usbvision_v4l2_read(struct file *file, char *buf,
4695 4703
4696static int usbvision_v4l2_mmap(struct file *file, struct vm_area_struct *vma) 4704static int usbvision_v4l2_mmap(struct file *file, struct vm_area_struct *vma)
4697{ 4705{
4706 unsigned long size = vma->vm_end - vma->vm_start,
4707 start = vma->vm_start;
4708 void *pos;
4709 u32 i;
4710
4698 struct video_device *dev = video_devdata(file); 4711 struct video_device *dev = video_devdata(file);
4699 struct usb_usbvision *usbvision = (struct usb_usbvision *) video_get_drvdata(dev); 4712 struct usb_usbvision *usbvision = (struct usb_usbvision *) video_get_drvdata(dev);
4700 unsigned long start = vma->vm_start;
4701 unsigned long size = vma->vm_end-vma->vm_start;
4702
4703 unsigned long page, pos;
4704 4713
4705 if (!USBVISION_IS_OPERATIONAL(usbvision)) 4714 if (!USBVISION_IS_OPERATIONAL(usbvision))
4706 return -EFAULT; 4715 return -EFAULT;
4707 4716
4708 if (size > (((USBVISION_NUMFRAMES * usbvision->max_frame_size) + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1))) 4717 if (!(vma->vm_flags & VM_WRITE) ||
4718 size != PAGE_ALIGN(usbvision->max_frame_size)) {
4719 return -EINVAL;
4720 }
4721
4722 for (i = 0; i < USBVISION_NUMFRAMES; i++) {
4723 if (((usbvision->max_frame_size*i) >> PAGE_SHIFT) == vma->vm_pgoff)
4724 break;
4725 }
4726 if (i == USBVISION_NUMFRAMES) {
4727 PDEBUG(DBG_FUNC, "mmap: user supplied mapping address is out of range");
4709 return -EINVAL; 4728 return -EINVAL;
4729 }
4710 4730
4711 pos = (unsigned long) usbvision->fbuf; 4731 /* VM_IO is eventually going to replace PageReserved altogether */
4732 vma->vm_flags |= VM_IO;
4733 vma->vm_flags |= VM_RESERVED; /* avoid to swap out this VMA */
4734
4735 pos = usbvision->frame[i].data;
4712 while (size > 0) { 4736 while (size > 0) {
4713 4737
4714// Really ugly.... 4738 if (vm_insert_page(vma, start, vmalloc_to_page(pos))) {
4715 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,10) //Compatibility for 2.6.10+ kernels 4739 PDEBUG(DBG_FUNC, "mmap: vm_insert_page failed");
4716 page = vmalloc_to_pfn((void *)pos);
4717 if (remap_pfn_range(vma, start, page, PAGE_SIZE, PAGE_SHARED)) {
4718 return -EAGAIN;
4719 }
4720 #else //Compatibility for 2.6.0 - 2.6.9 kernels
4721 page = usbvision_kvirt_to_pa(pos);
4722 if (remap_page_range(vma, start, page, PAGE_SIZE, PAGE_SHARED)) {
4723 return -EAGAIN; 4740 return -EAGAIN;
4724 } 4741 }
4725 #endif
4726 start += PAGE_SIZE; 4742 start += PAGE_SIZE;
4727 pos += PAGE_SIZE; 4743 pos += PAGE_SIZE;
4728 if (size > PAGE_SIZE) 4744 size -= PAGE_SIZE;
4729 size -= PAGE_SIZE;
4730 else
4731 size = 0;
4732 } 4745 }
4733 4746
4734 return 0; 4747 return 0;