diff options
author | Thierry MERLE <thierry.merle@free.fr> | 2006-12-04 06:31:24 -0500 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@infradead.org> | 2006-12-10 06:05:48 -0500 |
commit | 40bad67840aa6856cb39a431510a57d940017898 (patch) | |
tree | 2ce2b00bf379e7c41fb7ef983537f183108d51d9 /drivers/media | |
parent | 3084920b555b3ba73590430b2e03d9167db23e8e (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.c | 105 |
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 | ||
4696 | static int usbvision_v4l2_mmap(struct file *file, struct vm_area_struct *vma) | 4704 | static 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; |