V4L/DVB: pwc: fully convert driver to V4L2
Remove the V4L1 API from this driver, making it fully V4L2. Also fix a bug where the /dev/videoX device was created too early, which led to initialization problems of the camera, making it unable to capture video. Signed-off-by: Hans Verkuil <hverkuil@xs4all.nl> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
This commit is contained in:
parent
a1de2e4b72
commit
479567ce3a
|
@ -1,6 +1,6 @@
|
||||||
config USB_PWC
|
config USB_PWC
|
||||||
tristate "USB Philips Cameras"
|
tristate "USB Philips Cameras"
|
||||||
depends on VIDEO_V4L1
|
depends on VIDEO_V4L2
|
||||||
---help---
|
---help---
|
||||||
Say Y or M here if you want to use one of these Philips & OEM
|
Say Y or M here if you want to use one of these Philips & OEM
|
||||||
webcams:
|
webcams:
|
||||||
|
|
|
@ -261,7 +261,7 @@ static int set_video_mode_Nala(struct pwc_device *pdev, int size, int frames)
|
||||||
PWC_DEBUG_MODULE("Failed to send video command... %d\n", ret);
|
PWC_DEBUG_MODULE("Failed to send video command... %d\n", ret);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
if (pEntry->compressed && pdev->vpalette != VIDEO_PALETTE_RAW)
|
if (pEntry->compressed && pdev->pixfmt == V4L2_PIX_FMT_YUV420)
|
||||||
pwc_dec1_init(pdev->type, pdev->release, buf, pdev->decompress_data);
|
pwc_dec1_init(pdev->type, pdev->release, buf, pdev->decompress_data);
|
||||||
|
|
||||||
pdev->cmd_len = 3;
|
pdev->cmd_len = 3;
|
||||||
|
@ -321,7 +321,7 @@ static int set_video_mode_Timon(struct pwc_device *pdev, int size, int frames, i
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
if (pChoose->bandlength > 0 && pdev->vpalette != VIDEO_PALETTE_RAW)
|
if (pChoose->bandlength > 0 && pdev->pixfmt == V4L2_PIX_FMT_YUV420)
|
||||||
pwc_dec23_init(pdev, pdev->type, buf);
|
pwc_dec23_init(pdev, pdev->type, buf);
|
||||||
|
|
||||||
pdev->cmd_len = 13;
|
pdev->cmd_len = 13;
|
||||||
|
@ -356,7 +356,7 @@ static int set_video_mode_Kiara(struct pwc_device *pdev, int size, int frames, i
|
||||||
fps = (frames / 5) - 1;
|
fps = (frames / 5) - 1;
|
||||||
|
|
||||||
/* special case: VGA @ 5 fps and snapshot is raw bayer mode */
|
/* special case: VGA @ 5 fps and snapshot is raw bayer mode */
|
||||||
if (size == PSZ_VGA && frames == 5 && snapshot && pdev->vpalette == VIDEO_PALETTE_RAW)
|
if (size == PSZ_VGA && frames == 5 && snapshot && pdev->pixfmt != V4L2_PIX_FMT_YUV420)
|
||||||
{
|
{
|
||||||
/* Only available in case the raw palette is selected or
|
/* Only available in case the raw palette is selected or
|
||||||
we have the decompressor available. This mode is
|
we have the decompressor available. This mode is
|
||||||
|
@ -394,7 +394,7 @@ static int set_video_mode_Kiara(struct pwc_device *pdev, int size, int frames, i
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
if (pChoose->bandlength > 0 && pdev->vpalette != VIDEO_PALETTE_RAW)
|
if (pChoose->bandlength > 0 && pdev->pixfmt == V4L2_PIX_FMT_YUV420)
|
||||||
pwc_dec23_init(pdev, pdev->type, buf);
|
pwc_dec23_init(pdev, pdev->type, buf);
|
||||||
|
|
||||||
pdev->cmd_len = 12;
|
pdev->cmd_len = 12;
|
||||||
|
@ -429,7 +429,7 @@ int pwc_set_video_mode(struct pwc_device *pdev, int width, int height, int frame
|
||||||
{
|
{
|
||||||
int ret, size;
|
int ret, size;
|
||||||
|
|
||||||
PWC_DEBUG_FLOW("set_video_mode(%dx%d @ %d, palette %d).\n", width, height, frames, pdev->vpalette);
|
PWC_DEBUG_FLOW("set_video_mode(%dx%d @ %d, pixfmt %08x).\n", width, height, frames, pdev->pixfmt);
|
||||||
size = pwc_decode_size(pdev, width, height);
|
size = pwc_decode_size(pdev, width, height);
|
||||||
if (size < 0) {
|
if (size < 0) {
|
||||||
PWC_DEBUG_MODULE("Could not find suitable size.\n");
|
PWC_DEBUG_MODULE("Could not find suitable size.\n");
|
||||||
|
@ -519,13 +519,13 @@ static void pwc_set_image_buffer_size(struct pwc_device *pdev)
|
||||||
{
|
{
|
||||||
int i, factor = 0;
|
int i, factor = 0;
|
||||||
|
|
||||||
/* for PALETTE_YUV420P */
|
/* for V4L2_PIX_FMT_YUV420 */
|
||||||
switch(pdev->vpalette)
|
switch (pdev->pixfmt) {
|
||||||
{
|
case V4L2_PIX_FMT_YUV420:
|
||||||
case VIDEO_PALETTE_YUV420P:
|
|
||||||
factor = 6;
|
factor = 6;
|
||||||
break;
|
break;
|
||||||
case VIDEO_PALETTE_RAW:
|
case V4L2_PIX_FMT_PWC1:
|
||||||
|
case V4L2_PIX_FMT_PWC2:
|
||||||
factor = 6; /* can be uncompressed YUV420P */
|
factor = 6; /* can be uncompressed YUV420P */
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1365,7 +1365,7 @@ static ssize_t pwc_video_read(struct file *file, char __user *buf,
|
||||||
}
|
}
|
||||||
|
|
||||||
PWC_DEBUG_READ("Copying data to user space.\n");
|
PWC_DEBUG_READ("Copying data to user space.\n");
|
||||||
if (pdev->vpalette == VIDEO_PALETTE_RAW)
|
if (pdev->pixfmt != V4L2_PIX_FMT_YUV420)
|
||||||
bytes_to_read = pdev->frame_size + sizeof(struct pwc_raw_frame);
|
bytes_to_read = pdev->frame_size + sizeof(struct pwc_raw_frame);
|
||||||
else
|
else
|
||||||
bytes_to_read = pdev->view.size;
|
bytes_to_read = pdev->view.size;
|
||||||
|
@ -1800,13 +1800,6 @@ static int usb_pwc_probe(struct usb_interface *intf, const struct usb_device_id
|
||||||
}
|
}
|
||||||
|
|
||||||
pdev->vdev->release = video_device_release;
|
pdev->vdev->release = video_device_release;
|
||||||
rc = video_register_device(pdev->vdev, VFL_TYPE_GRABBER, video_nr);
|
|
||||||
if (rc < 0) {
|
|
||||||
PWC_ERROR("Failed to register as video device (%d).\n", rc);
|
|
||||||
goto err_video_release;
|
|
||||||
}
|
|
||||||
|
|
||||||
PWC_INFO("Registered as %s.\n", video_device_node_name(pdev->vdev));
|
|
||||||
|
|
||||||
/* occupy slot */
|
/* occupy slot */
|
||||||
if (hint < MAX_DEV_HINTS)
|
if (hint < MAX_DEV_HINTS)
|
||||||
|
@ -1814,14 +1807,22 @@ static int usb_pwc_probe(struct usb_interface *intf, const struct usb_device_id
|
||||||
|
|
||||||
PWC_DEBUG_PROBE("probe() function returning struct at 0x%p.\n", pdev);
|
PWC_DEBUG_PROBE("probe() function returning struct at 0x%p.\n", pdev);
|
||||||
usb_set_intfdata(intf, pdev);
|
usb_set_intfdata(intf, pdev);
|
||||||
rc = pwc_create_sysfs_files(pdev->vdev);
|
|
||||||
if (rc)
|
|
||||||
goto err_video_unreg;
|
|
||||||
|
|
||||||
/* Set the leds off */
|
/* Set the leds off */
|
||||||
pwc_set_leds(pdev, 0, 0);
|
pwc_set_leds(pdev, 0, 0);
|
||||||
pwc_camera_power(pdev, 0);
|
pwc_camera_power(pdev, 0);
|
||||||
|
|
||||||
|
rc = video_register_device(pdev->vdev, VFL_TYPE_GRABBER, video_nr);
|
||||||
|
if (rc < 0) {
|
||||||
|
PWC_ERROR("Failed to register as video device (%d).\n", rc);
|
||||||
|
goto err_video_release;
|
||||||
|
}
|
||||||
|
rc = pwc_create_sysfs_files(pdev->vdev);
|
||||||
|
if (rc)
|
||||||
|
goto err_video_unreg;
|
||||||
|
|
||||||
|
PWC_INFO("Registered as %s.\n", video_device_node_name(pdev->vdev));
|
||||||
|
|
||||||
#ifdef CONFIG_USB_PWC_INPUT_EVDEV
|
#ifdef CONFIG_USB_PWC_INPUT_EVDEV
|
||||||
/* register webcam snapshot button input device */
|
/* register webcam snapshot button input device */
|
||||||
pdev->button_dev = input_allocate_device();
|
pdev->button_dev = input_allocate_device();
|
||||||
|
|
|
@ -47,7 +47,7 @@ int pwc_decode_size(struct pwc_device *pdev, int width, int height)
|
||||||
you don't have the decompressor loaded or use RAW mode,
|
you don't have the decompressor loaded or use RAW mode,
|
||||||
the maximum viewable size is smaller.
|
the maximum viewable size is smaller.
|
||||||
*/
|
*/
|
||||||
if (pdev->vpalette == VIDEO_PALETTE_RAW)
|
if (pdev->pixfmt != V4L2_PIX_FMT_YUV420)
|
||||||
{
|
{
|
||||||
if (width > pdev->abs_max.x || height > pdev->abs_max.y)
|
if (width > pdev->abs_max.x || height > pdev->abs_max.y)
|
||||||
{
|
{
|
||||||
|
@ -123,7 +123,7 @@ void pwc_construct(struct pwc_device *pdev)
|
||||||
pdev->frame_header_size = 0;
|
pdev->frame_header_size = 0;
|
||||||
pdev->frame_trailer_size = 0;
|
pdev->frame_trailer_size = 0;
|
||||||
}
|
}
|
||||||
pdev->vpalette = VIDEO_PALETTE_YUV420P; /* default */
|
pdev->pixfmt = V4L2_PIX_FMT_YUV420; /* default */
|
||||||
pdev->view_min.size = pdev->view_min.x * pdev->view_min.y;
|
pdev->view_min.size = pdev->view_min.x * pdev->view_min.y;
|
||||||
pdev->view_max.size = pdev->view_max.x * pdev->view_max.y;
|
pdev->view_max.size = pdev->view_max.x * pdev->view_max.y;
|
||||||
/* length of image, in YUV format; always allocate enough memory. */
|
/* length of image, in YUV format; always allocate enough memory. */
|
||||||
|
|
|
@ -54,7 +54,7 @@ int pwc_decompress(struct pwc_device *pdev)
|
||||||
yuv = fbuf->data + pdev->frame_header_size; /* Skip header */
|
yuv = fbuf->data + pdev->frame_header_size; /* Skip header */
|
||||||
|
|
||||||
/* Raw format; that's easy... */
|
/* Raw format; that's easy... */
|
||||||
if (pdev->vpalette == VIDEO_PALETTE_RAW)
|
if (pdev->pixfmt != V4L2_PIX_FMT_YUV420)
|
||||||
{
|
{
|
||||||
struct pwc_raw_frame *raw_frame = image;
|
struct pwc_raw_frame *raw_frame = image;
|
||||||
raw_frame->type = cpu_to_le16(pdev->type);
|
raw_frame->type = cpu_to_le16(pdev->type);
|
||||||
|
|
|
@ -216,7 +216,7 @@ static void pwc_vidioc_fill_fmt(const struct pwc_device *pdev, struct v4l2_forma
|
||||||
f->fmt.pix.width = pdev->view.x;
|
f->fmt.pix.width = pdev->view.x;
|
||||||
f->fmt.pix.height = pdev->view.y;
|
f->fmt.pix.height = pdev->view.y;
|
||||||
f->fmt.pix.field = V4L2_FIELD_NONE;
|
f->fmt.pix.field = V4L2_FIELD_NONE;
|
||||||
if (pdev->vpalette == VIDEO_PALETTE_YUV420P) {
|
if (pdev->pixfmt == V4L2_PIX_FMT_YUV420) {
|
||||||
f->fmt.pix.pixelformat = V4L2_PIX_FMT_YUV420;
|
f->fmt.pix.pixelformat = V4L2_PIX_FMT_YUV420;
|
||||||
f->fmt.pix.bytesperline = (f->fmt.pix.width * 3)/2;
|
f->fmt.pix.bytesperline = (f->fmt.pix.width * 3)/2;
|
||||||
f->fmt.pix.sizeimage = f->fmt.pix.height * f->fmt.pix.bytesperline;
|
f->fmt.pix.sizeimage = f->fmt.pix.height * f->fmt.pix.bytesperline;
|
||||||
|
@ -304,10 +304,10 @@ static int pwc_vidioc_set_fmt(struct pwc_device *pdev, struct v4l2_format *f)
|
||||||
fps = pdev->vframes;
|
fps = pdev->vframes;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pixelformat == V4L2_PIX_FMT_YUV420)
|
if (pixelformat != V4L2_PIX_FMT_YUV420 &&
|
||||||
pdev->vpalette = VIDEO_PALETTE_YUV420P;
|
pixelformat != V4L2_PIX_FMT_PWC1 &&
|
||||||
else
|
pixelformat != V4L2_PIX_FMT_PWC2)
|
||||||
pdev->vpalette = VIDEO_PALETTE_RAW;
|
return -EINVAL;
|
||||||
|
|
||||||
PWC_DEBUG_IOCTL("Try to change format to: width=%d height=%d fps=%d "
|
PWC_DEBUG_IOCTL("Try to change format to: width=%d height=%d fps=%d "
|
||||||
"compression=%d snapshot=%d format=%c%c%c%c\n",
|
"compression=%d snapshot=%d format=%c%c%c%c\n",
|
||||||
|
@ -330,6 +330,8 @@ static int pwc_vidioc_set_fmt(struct pwc_device *pdev, struct v4l2_format *f)
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
|
pdev->pixfmt = pixelformat;
|
||||||
|
|
||||||
pwc_vidioc_fill_fmt(pdev, f);
|
pwc_vidioc_fill_fmt(pdev, f);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -357,152 +359,7 @@ long pwc_video_do_ioctl(struct file *file, unsigned int cmd, void *arg)
|
||||||
|
|
||||||
|
|
||||||
switch (cmd) {
|
switch (cmd) {
|
||||||
/* Query cabapilities */
|
#ifdef CONFIG_VIDEO_V4L1_COMPAT
|
||||||
case VIDIOCGCAP:
|
|
||||||
{
|
|
||||||
struct video_capability *caps = arg;
|
|
||||||
|
|
||||||
strcpy(caps->name, vdev->name);
|
|
||||||
caps->type = VID_TYPE_CAPTURE;
|
|
||||||
caps->channels = 1;
|
|
||||||
caps->audios = 1;
|
|
||||||
caps->minwidth = pdev->view_min.x;
|
|
||||||
caps->minheight = pdev->view_min.y;
|
|
||||||
caps->maxwidth = pdev->view_max.x;
|
|
||||||
caps->maxheight = pdev->view_max.y;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Channel functions (simulate 1 channel) */
|
|
||||||
case VIDIOCGCHAN:
|
|
||||||
{
|
|
||||||
struct video_channel *v = arg;
|
|
||||||
|
|
||||||
if (v->channel != 0)
|
|
||||||
return -EINVAL;
|
|
||||||
v->flags = 0;
|
|
||||||
v->tuners = 0;
|
|
||||||
v->type = VIDEO_TYPE_CAMERA;
|
|
||||||
strcpy(v->name, "Webcam");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
case VIDIOCSCHAN:
|
|
||||||
{
|
|
||||||
/* The spec says the argument is an integer, but
|
|
||||||
the bttv driver uses a video_channel arg, which
|
|
||||||
makes sense becasue it also has the norm flag.
|
|
||||||
*/
|
|
||||||
struct video_channel *v = arg;
|
|
||||||
if (v->channel != 0)
|
|
||||||
return -EINVAL;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* Picture functions; contrast etc. */
|
|
||||||
case VIDIOCGPICT:
|
|
||||||
{
|
|
||||||
struct video_picture *p = arg;
|
|
||||||
int val;
|
|
||||||
|
|
||||||
val = pwc_get_brightness(pdev);
|
|
||||||
if (val >= 0)
|
|
||||||
p->brightness = (val<<9);
|
|
||||||
else
|
|
||||||
p->brightness = 0xffff;
|
|
||||||
val = pwc_get_contrast(pdev);
|
|
||||||
if (val >= 0)
|
|
||||||
p->contrast = (val<<10);
|
|
||||||
else
|
|
||||||
p->contrast = 0xffff;
|
|
||||||
/* Gamma, Whiteness, what's the difference? :) */
|
|
||||||
val = pwc_get_gamma(pdev);
|
|
||||||
if (val >= 0)
|
|
||||||
p->whiteness = (val<<11);
|
|
||||||
else
|
|
||||||
p->whiteness = 0xffff;
|
|
||||||
if (pwc_get_saturation(pdev, &val)<0)
|
|
||||||
p->colour = 0xffff;
|
|
||||||
else
|
|
||||||
p->colour = 32768 + val * 327;
|
|
||||||
p->depth = 24;
|
|
||||||
p->palette = pdev->vpalette;
|
|
||||||
p->hue = 0xFFFF; /* N/A */
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case VIDIOCSPICT:
|
|
||||||
{
|
|
||||||
struct video_picture *p = arg;
|
|
||||||
/*
|
|
||||||
* FIXME: Suppose we are mid read
|
|
||||||
ANSWER: No problem: the firmware of the camera
|
|
||||||
can handle brightness/contrast/etc
|
|
||||||
changes at _any_ time, and the palette
|
|
||||||
is used exactly once in the uncompress
|
|
||||||
routine.
|
|
||||||
*/
|
|
||||||
pwc_set_brightness(pdev, p->brightness);
|
|
||||||
pwc_set_contrast(pdev, p->contrast);
|
|
||||||
pwc_set_gamma(pdev, p->whiteness);
|
|
||||||
pwc_set_saturation(pdev, (p->colour-32768)/327);
|
|
||||||
if (p->palette && p->palette != pdev->vpalette) {
|
|
||||||
switch (p->palette) {
|
|
||||||
case VIDEO_PALETTE_YUV420P:
|
|
||||||
case VIDEO_PALETTE_RAW:
|
|
||||||
pdev->vpalette = p->palette;
|
|
||||||
return pwc_try_video_mode(pdev, pdev->image.x, pdev->image.y, pdev->vframes, pdev->vcompression, pdev->vsnapshot);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
return -EINVAL;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Window/size parameters */
|
|
||||||
case VIDIOCGWIN:
|
|
||||||
{
|
|
||||||
struct video_window *vw = arg;
|
|
||||||
|
|
||||||
vw->x = 0;
|
|
||||||
vw->y = 0;
|
|
||||||
vw->width = pdev->view.x;
|
|
||||||
vw->height = pdev->view.y;
|
|
||||||
vw->chromakey = 0;
|
|
||||||
vw->flags = (pdev->vframes << PWC_FPS_SHIFT) |
|
|
||||||
(pdev->vsnapshot ? PWC_FPS_SNAPSHOT : 0);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case VIDIOCSWIN:
|
|
||||||
{
|
|
||||||
struct video_window *vw = arg;
|
|
||||||
int fps, snapshot, ret;
|
|
||||||
|
|
||||||
fps = (vw->flags & PWC_FPS_FRMASK) >> PWC_FPS_SHIFT;
|
|
||||||
snapshot = vw->flags & PWC_FPS_SNAPSHOT;
|
|
||||||
if (fps == 0)
|
|
||||||
fps = pdev->vframes;
|
|
||||||
if (pdev->view.x == vw->width && pdev->view.y && fps == pdev->vframes && snapshot == pdev->vsnapshot)
|
|
||||||
return 0;
|
|
||||||
ret = pwc_try_video_mode(pdev, vw->width, vw->height, fps, pdev->vcompression, snapshot);
|
|
||||||
if (ret)
|
|
||||||
return ret;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* We don't have overlay support (yet) */
|
|
||||||
case VIDIOCGFBUF:
|
|
||||||
{
|
|
||||||
struct video_buffer *vb = arg;
|
|
||||||
|
|
||||||
memset(vb,0,sizeof(*vb));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* mmap() functions */
|
/* mmap() functions */
|
||||||
case VIDIOCGMBUF:
|
case VIDIOCGMBUF:
|
||||||
{
|
{
|
||||||
|
@ -517,164 +374,7 @@ long pwc_video_do_ioctl(struct file *file, unsigned int cmd, void *arg)
|
||||||
vm->offsets[i] = i * pdev->len_per_image;
|
vm->offsets[i] = i * pdev->len_per_image;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
case VIDIOCMCAPTURE:
|
|
||||||
{
|
|
||||||
/* Start capture into a given image buffer (called 'frame' in video_mmap structure) */
|
|
||||||
struct video_mmap *vm = arg;
|
|
||||||
|
|
||||||
PWC_DEBUG_READ("VIDIOCMCAPTURE: %dx%d, frame %d, format %d\n", vm->width, vm->height, vm->frame, vm->format);
|
|
||||||
if (vm->frame < 0 || vm->frame >= pwc_mbufs)
|
|
||||||
return -EINVAL;
|
|
||||||
|
|
||||||
/* xawtv is nasty. It probes the available palettes
|
|
||||||
by setting a very small image size and trying
|
|
||||||
various palettes... The driver doesn't support
|
|
||||||
such small images, so I'm working around it.
|
|
||||||
*/
|
|
||||||
if (vm->format)
|
|
||||||
{
|
|
||||||
switch (vm->format)
|
|
||||||
{
|
|
||||||
case VIDEO_PALETTE_YUV420P:
|
|
||||||
case VIDEO_PALETTE_RAW:
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
return -EINVAL;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((vm->width != pdev->view.x || vm->height != pdev->view.y) &&
|
|
||||||
(vm->width >= pdev->view_min.x && vm->height >= pdev->view_min.y)) {
|
|
||||||
int ret;
|
|
||||||
|
|
||||||
PWC_DEBUG_OPEN("VIDIOCMCAPTURE: changing size to please xawtv :-(.\n");
|
|
||||||
ret = pwc_try_video_mode(pdev, vm->width, vm->height, pdev->vframes, pdev->vcompression, pdev->vsnapshot);
|
|
||||||
if (ret)
|
|
||||||
return ret;
|
|
||||||
} /* ... size mismatch */
|
|
||||||
|
|
||||||
/* FIXME: should we lock here? */
|
|
||||||
if (pdev->image_used[vm->frame])
|
|
||||||
return -EBUSY; /* buffer wasn't available. Bummer */
|
|
||||||
pdev->image_used[vm->frame] = 1;
|
|
||||||
|
|
||||||
/* Okay, we're done here. In the SYNC call we wait until a
|
|
||||||
frame comes available, then expand image into the given
|
|
||||||
buffer.
|
|
||||||
In contrast to the CPiA cam the Philips cams deliver a
|
|
||||||
constant stream, almost like a grabber card. Also,
|
|
||||||
we have separate buffers for the rawdata and the image,
|
|
||||||
meaning we can nearly always expand into the requested buffer.
|
|
||||||
*/
|
|
||||||
PWC_DEBUG_READ("VIDIOCMCAPTURE done.\n");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case VIDIOCSYNC:
|
|
||||||
{
|
|
||||||
/* The doc says: "Whenever a buffer is used it should
|
|
||||||
call VIDIOCSYNC to free this frame up and continue."
|
|
||||||
|
|
||||||
The only odd thing about this whole procedure is
|
|
||||||
that MCAPTURE flags the buffer as "in use", and
|
|
||||||
SYNC immediately unmarks it, while it isn't
|
|
||||||
after SYNC that you know that the buffer actually
|
|
||||||
got filled! So you better not start a CAPTURE in
|
|
||||||
the same frame immediately (use double buffering).
|
|
||||||
This is not a problem for this cam, since it has
|
|
||||||
extra intermediate buffers, but a hardware
|
|
||||||
grabber card will then overwrite the buffer
|
|
||||||
you're working on.
|
|
||||||
*/
|
|
||||||
int *mbuf = arg;
|
|
||||||
int ret;
|
|
||||||
|
|
||||||
PWC_DEBUG_READ("VIDIOCSYNC called (%d).\n", *mbuf);
|
|
||||||
|
|
||||||
/* bounds check */
|
|
||||||
if (*mbuf < 0 || *mbuf >= pwc_mbufs)
|
|
||||||
return -EINVAL;
|
|
||||||
/* check if this buffer was requested anyway */
|
|
||||||
if (pdev->image_used[*mbuf] == 0)
|
|
||||||
return -EINVAL;
|
|
||||||
|
|
||||||
/* Add ourselves to the frame wait-queue.
|
|
||||||
|
|
||||||
FIXME: needs auditing for safety.
|
|
||||||
QUESTION: In what respect? I think that using the
|
|
||||||
frameq is safe now.
|
|
||||||
*/
|
|
||||||
add_wait_queue(&pdev->frameq, &wait);
|
|
||||||
while (pdev->full_frames == NULL) {
|
|
||||||
/* Check for unplugged/etc. here */
|
|
||||||
if (pdev->error_status) {
|
|
||||||
remove_wait_queue(&pdev->frameq, &wait);
|
|
||||||
set_current_state(TASK_RUNNING);
|
|
||||||
return -pdev->error_status;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (signal_pending(current)) {
|
|
||||||
remove_wait_queue(&pdev->frameq, &wait);
|
|
||||||
set_current_state(TASK_RUNNING);
|
|
||||||
return -ERESTARTSYS;
|
|
||||||
}
|
|
||||||
schedule();
|
|
||||||
set_current_state(TASK_INTERRUPTIBLE);
|
|
||||||
}
|
|
||||||
remove_wait_queue(&pdev->frameq, &wait);
|
|
||||||
set_current_state(TASK_RUNNING);
|
|
||||||
|
|
||||||
/* The frame is ready. Expand in the image buffer
|
|
||||||
requested by the user. I don't care if you
|
|
||||||
mmap() 5 buffers and request data in this order:
|
|
||||||
buffer 4 2 3 0 1 2 3 0 4 3 1 . . .
|
|
||||||
Grabber hardware may not be so forgiving.
|
|
||||||
*/
|
|
||||||
PWC_DEBUG_READ("VIDIOCSYNC: frame ready.\n");
|
|
||||||
pdev->fill_image = *mbuf; /* tell in which buffer we want the image to be expanded */
|
|
||||||
/* Decompress, etc */
|
|
||||||
ret = pwc_handle_frame(pdev);
|
|
||||||
pdev->image_used[*mbuf] = 0;
|
|
||||||
if (ret)
|
|
||||||
return -EFAULT;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case VIDIOCGAUDIO:
|
|
||||||
{
|
|
||||||
struct video_audio *v = arg;
|
|
||||||
|
|
||||||
strcpy(v->name, "Microphone");
|
|
||||||
v->audio = -1; /* unknown audio minor */
|
|
||||||
v->flags = 0;
|
|
||||||
v->mode = VIDEO_SOUND_MONO;
|
|
||||||
v->volume = 0;
|
|
||||||
v->bass = 0;
|
|
||||||
v->treble = 0;
|
|
||||||
v->balance = 0x8000;
|
|
||||||
v->step = 1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case VIDIOCSAUDIO:
|
|
||||||
{
|
|
||||||
/* Dummy: nothing can be set */
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case VIDIOCGUNIT:
|
|
||||||
{
|
|
||||||
struct video_unit *vu = arg;
|
|
||||||
|
|
||||||
vu->video = pdev->vdev->minor & 0x3F;
|
|
||||||
vu->audio = -1; /* not known yet */
|
|
||||||
vu->vbi = -1;
|
|
||||||
vu->radio = -1;
|
|
||||||
vu->teletext = -1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* V4L2 Layer */
|
/* V4L2 Layer */
|
||||||
case VIDIOC_QUERYCAP:
|
case VIDIOC_QUERYCAP:
|
||||||
|
@ -1081,7 +781,7 @@ long pwc_video_do_ioctl(struct file *file, unsigned int cmd, void *arg)
|
||||||
buf->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
|
buf->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
|
||||||
buf->index = index;
|
buf->index = index;
|
||||||
buf->m.offset = index * pdev->len_per_image;
|
buf->m.offset = index * pdev->len_per_image;
|
||||||
if (pdev->vpalette == VIDEO_PALETTE_RAW)
|
if (pdev->pixfmt != V4L2_PIX_FMT_YUV420)
|
||||||
buf->bytesused = pdev->frame_size + sizeof(struct pwc_raw_frame);
|
buf->bytesused = pdev->frame_size + sizeof(struct pwc_raw_frame);
|
||||||
else
|
else
|
||||||
buf->bytesused = pdev->view.size;
|
buf->bytesused = pdev->view.size;
|
||||||
|
@ -1158,7 +858,7 @@ long pwc_video_do_ioctl(struct file *file, unsigned int cmd, void *arg)
|
||||||
PWC_DEBUG_IOCTL("VIDIOC_DQBUF: after pwc_handle_frame\n");
|
PWC_DEBUG_IOCTL("VIDIOC_DQBUF: after pwc_handle_frame\n");
|
||||||
|
|
||||||
buf->index = pdev->fill_image;
|
buf->index = pdev->fill_image;
|
||||||
if (pdev->vpalette == VIDEO_PALETTE_RAW)
|
if (pdev->pixfmt != V4L2_PIX_FMT_YUV420)
|
||||||
buf->bytesused = pdev->frame_size + sizeof(struct pwc_raw_frame);
|
buf->bytesused = pdev->frame_size + sizeof(struct pwc_raw_frame);
|
||||||
else
|
else
|
||||||
buf->bytesused = pdev->view.size;
|
buf->bytesused = pdev->view.size;
|
||||||
|
|
|
@ -34,7 +34,7 @@
|
||||||
#include <linux/mm.h>
|
#include <linux/mm.h>
|
||||||
#include <linux/slab.h>
|
#include <linux/slab.h>
|
||||||
#include <asm/errno.h>
|
#include <asm/errno.h>
|
||||||
#include <linux/videodev.h>
|
#include <linux/videodev2.h>
|
||||||
#include <media/v4l2-common.h>
|
#include <media/v4l2-common.h>
|
||||||
#include <media/v4l2-ioctl.h>
|
#include <media/v4l2-ioctl.h>
|
||||||
#ifdef CONFIG_USB_PWC_INPUT_EVDEV
|
#ifdef CONFIG_USB_PWC_INPUT_EVDEV
|
||||||
|
@ -49,7 +49,7 @@
|
||||||
#define PWC_MINOR 0
|
#define PWC_MINOR 0
|
||||||
#define PWC_EXTRAMINOR 12
|
#define PWC_EXTRAMINOR 12
|
||||||
#define PWC_VERSION_CODE KERNEL_VERSION(PWC_MAJOR,PWC_MINOR,PWC_EXTRAMINOR)
|
#define PWC_VERSION_CODE KERNEL_VERSION(PWC_MAJOR,PWC_MINOR,PWC_EXTRAMINOR)
|
||||||
#define PWC_VERSION "10.0.13"
|
#define PWC_VERSION "10.0.14"
|
||||||
#define PWC_NAME "pwc"
|
#define PWC_NAME "pwc"
|
||||||
#define PFX PWC_NAME ": "
|
#define PFX PWC_NAME ": "
|
||||||
|
|
||||||
|
@ -180,7 +180,7 @@ struct pwc_device
|
||||||
int vcinterface; /* video control interface */
|
int vcinterface; /* video control interface */
|
||||||
int valternate; /* alternate interface needed */
|
int valternate; /* alternate interface needed */
|
||||||
int vframes, vsize; /* frames-per-second & size (see PSZ_*) */
|
int vframes, vsize; /* frames-per-second & size (see PSZ_*) */
|
||||||
int vpalette; /* palette: 420P, RAW or RGBBAYER */
|
int pixfmt; /* pixelformat: V4L2_PIX_FMT_YUV420 or raw: _PWC1, _PWC2 */
|
||||||
int vframe_count; /* received frames */
|
int vframe_count; /* received frames */
|
||||||
int vframes_dumped; /* counter for dumped frames */
|
int vframes_dumped; /* counter for dumped frames */
|
||||||
int vframes_error; /* frames received in error */
|
int vframes_error; /* frames received in error */
|
||||||
|
|
Loading…
Reference in New Issue