Commit 40bad678 authored by Thierry MERLE's avatar Thierry MERLE Committed by Mauro Carvalho Chehab

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: default avatarThierry MERLE <thierry.merle@free.fr>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab@infradead.org>
parent 3084920b
...@@ -364,8 +364,6 @@ ...@@ -364,8 +364,6 @@
#endif #endif
#include "usbvision.h" #include "usbvision.h"
#include "usbvision_ioctl.h"
#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__ #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__
#define EMAIL "joerg@heckenbach-aw.de" #define EMAIL "joerg@heckenbach-aw.de"
...@@ -2320,6 +2318,10 @@ static void usbvision_isocIrq(struct urb *urb, struct pt_regs *regs) ...@@ -2320,6 +2318,10 @@ static void usbvision_isocIrq(struct urb *urb, struct pt_regs *regs)
} }
} }
} }
else {
PDEBUG(DBG_IRQ, "received data, but no one needs it");
scratch_reset(usbvision);
}
usbvision->timeInIrq += jiffies - startTime; usbvision->timeInIrq += jiffies - startTime;
...@@ -3901,41 +3903,50 @@ static int usbvision_v4l2_do_ioctl(struct inode *inode, struct file *file, ...@@ -3901,41 +3903,50 @@ static int usbvision_v4l2_do_ioctl(struct inode *inode, struct file *file,
// if (debug & DBG_IOCTL) v4l_printk_ioctl(cmd); // if (debug & DBG_IOCTL) v4l_printk_ioctl(cmd);
switch (cmd) { switch (cmd) {
case UVIOCSREG:
#ifdef CONFIG_VIDEO_ADV_DEBUG
/* ioctls to allow direct acces to the NT100x registers */
case VIDIOC_INT_G_REGISTER:
{ {
struct usbvision_reg *usbvision_reg = arg; struct v4l2_register *reg = arg;
int errCode; int errCode;
errCode = usbvision_write_reg(usbvision, usbvision_reg->addr, usbvision_reg->value); if (reg->i2c_id != 0)
return -EINVAL;
/* NT100x has a 8-bit register space */
errCode = usbvision_read_reg(usbvision, reg->reg&0xff);
if (errCode < 0) { if (errCode < 0) {
err("%s: UVIOCSREG failed: error %d", __FUNCTION__, errCode); err("%s: VIDIOC_INT_G_REGISTER failed: error %d", __FUNCTION__, errCode);
} }
else { else {
PDEBUG(DBG_IOCTL, "UVIOCSREG addr=0x%02X, value=0x%02X", reg->val=(unsigned char)errCode;
usbvision_reg->addr, usbvision_reg->value); PDEBUG(DBG_IOCTL, "VIDIOC_INT_G_REGISTER reg=0x%02X, value=0x%02X",
errCode = 0; (unsigned int)reg->reg, reg->val);
errCode = 0; // No error
} }
return errCode; return errCode;
} }
case UVIOCGREG: case VIDIOC_INT_S_REGISTER:
{ {
struct usbvision_reg *usbvision_reg = arg; struct v4l2_register *reg = arg;
int errCode; int errCode;
errCode = usbvision_read_reg(usbvision, usbvision_reg->addr); if (reg->i2c_id != 0)
return -EINVAL;
if (!capable(CAP_SYS_ADMIN))
return -EPERM;
errCode = usbvision_write_reg(usbvision, reg->reg&0xff, reg->val);
if (errCode < 0) { if (errCode < 0) {
err("%s: UVIOCGREG failed: error %d", __FUNCTION__, errCode); err("%s: VIDIOC_INT_S_REGISTER failed: error %d", __FUNCTION__, errCode);
} }
else { else {
usbvision_reg->value=(unsigned char)errCode; PDEBUG(DBG_IOCTL, "VIDIOC_INT_S_REGISTER reg=0x%02X, value=0x%02X",
PDEBUG(DBG_IOCTL, "UVIOCGREG addr=0x%02X, value=0x%02X", (unsigned int)reg->reg, reg->val);
usbvision_reg->addr, usbvision_reg->value); errCode = 0;
errCode = 0; // No error
} }
return errCode; return 0;
} }
#endif
case VIDIOC_QUERYCAP: case VIDIOC_QUERYCAP:
{ {
struct v4l2_capability *vc=arg; struct v4l2_capability *vc=arg;
...@@ -4232,12 +4243,9 @@ static int usbvision_v4l2_do_ioctl(struct inode *inode, struct file *file, ...@@ -4232,12 +4243,9 @@ static int usbvision_v4l2_do_ioctl(struct inode *inode, struct file *file,
if(frame->grabstate == FrameState_Unused) if(frame->grabstate == FrameState_Unused)
vb->flags |= V4L2_BUF_FLAG_MAPPED; vb->flags |= V4L2_BUF_FLAG_MAPPED;
vb->memory = V4L2_MEMORY_MMAP; vb->memory = V4L2_MEMORY_MMAP;
if(vb->index == 0) {
vb->m.offset = 0; vb->m.offset = vb->index*MAX_FRAME_SIZE;
}
else {
vb->m.offset = MAX_FRAME_SIZE;
}
vb->memory = V4L2_MEMORY_MMAP; vb->memory = V4L2_MEMORY_MMAP;
vb->field = V4L2_FIELD_NONE; vb->field = V4L2_FIELD_NONE;
vb->length = MAX_FRAME_SIZE; vb->length = MAX_FRAME_SIZE;
...@@ -4695,40 +4703,45 @@ static ssize_t usbvision_v4l2_read(struct file *file, char *buf, ...@@ -4695,40 +4703,45 @@ static ssize_t usbvision_v4l2_read(struct file *file, char *buf,
static int usbvision_v4l2_mmap(struct file *file, struct vm_area_struct *vma) static int usbvision_v4l2_mmap(struct file *file, struct vm_area_struct *vma)
{ {
unsigned long size = vma->vm_end - vma->vm_start,
start = vma->vm_start;
void *pos;
u32 i;
struct video_device *dev = video_devdata(file); struct video_device *dev = video_devdata(file);
struct usb_usbvision *usbvision = (struct usb_usbvision *) video_get_drvdata(dev); struct usb_usbvision *usbvision = (struct usb_usbvision *) video_get_drvdata(dev);
unsigned long start = vma->vm_start;
unsigned long size = vma->vm_end-vma->vm_start;
unsigned long page, pos;
if (!USBVISION_IS_OPERATIONAL(usbvision)) if (!USBVISION_IS_OPERATIONAL(usbvision))
return -EFAULT; return -EFAULT;
if (size > (((USBVISION_NUMFRAMES * usbvision->max_frame_size) + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1))) if (!(vma->vm_flags & VM_WRITE) ||
size != PAGE_ALIGN(usbvision->max_frame_size)) {
return -EINVAL; return -EINVAL;
}
pos = (unsigned long) usbvision->fbuf; for (i = 0; i < USBVISION_NUMFRAMES; i++) {
if (((usbvision->max_frame_size*i) >> PAGE_SHIFT) == vma->vm_pgoff)
break;
}
if (i == USBVISION_NUMFRAMES) {
PDEBUG(DBG_FUNC, "mmap: user supplied mapping address is out of range");
return -EINVAL;
}
/* VM_IO is eventually going to replace PageReserved altogether */
vma->vm_flags |= VM_IO;
vma->vm_flags |= VM_RESERVED; /* avoid to swap out this VMA */
pos = usbvision->frame[i].data;
while (size > 0) { while (size > 0) {
// Really ugly.... if (vm_insert_page(vma, start, vmalloc_to_page(pos))) {
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,10) //Compatibility for 2.6.10+ kernels PDEBUG(DBG_FUNC, "mmap: vm_insert_page failed");
page = vmalloc_to_pfn((void *)pos);
if (remap_pfn_range(vma, start, page, PAGE_SIZE, PAGE_SHARED)) {
return -EAGAIN; return -EAGAIN;
} }
#else //Compatibility for 2.6.0 - 2.6.9 kernels
page = usbvision_kvirt_to_pa(pos);
if (remap_page_range(vma, start, page, PAGE_SIZE, PAGE_SHARED)) {
return -EAGAIN;
}
#endif
start += PAGE_SIZE; start += PAGE_SIZE;
pos += PAGE_SIZE; pos += PAGE_SIZE;
if (size > PAGE_SIZE)
size -= PAGE_SIZE; size -= PAGE_SIZE;
else
size = 0;
} }
return 0; return 0;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment