1 /* Linux driver for Philips webcam
2 USB and Video4Linux interface part.
3 (C) 1999-2004 Nemosoft Unv.
4 (C) 2004-2006 Luc Saillard (luc@saillard.org)
6 NOTE: this version of pwc is an unofficial (modified) release of pwc & pcwx
7 driver and thus may have bugs that are not present in the original version.
8 Please send bug reports and support requests to <luc@saillard.org>.
9 The decompression routines have been implemented by reverse-engineering the
10 Nemosoft binary pwcx module. Caveat emptor.
12 This program is free software; you can redistribute it and/or modify
13 it under the terms of the GNU General Public License as published by
14 the Free Software Foundation; either version 2 of the License, or
15 (at your option) any later version.
17 This program is distributed in the hope that it will be useful,
18 but WITHOUT ANY WARRANTY; without even the implied warranty of
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 GNU General Public License for more details.
22 You should have received a copy of the GNU General Public License
23 along with this program; if not, write to the Free Software
24 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
28 #include <linux/errno.h>
29 #include <linux/init.h>
31 #include <linux/module.h>
32 #include <linux/poll.h>
33 #include <linux/slab.h>
34 #include <linux/vmalloc.h>
39 static struct v4l2_queryctrl pwc_controls[] = {
41 .id = V4L2_CID_BRIGHTNESS,
42 .type = V4L2_CTRL_TYPE_INTEGER,
50 .id = V4L2_CID_CONTRAST,
51 .type = V4L2_CTRL_TYPE_INTEGER,
59 .id = V4L2_CID_SATURATION,
60 .type = V4L2_CTRL_TYPE_INTEGER,
69 .type = V4L2_CTRL_TYPE_INTEGER,
77 .id = V4L2_CID_RED_BALANCE,
78 .type = V4L2_CTRL_TYPE_INTEGER,
86 .id = V4L2_CID_BLUE_BALANCE,
87 .type = V4L2_CTRL_TYPE_INTEGER,
95 .id = V4L2_CID_AUTO_WHITE_BALANCE,
96 .type = V4L2_CTRL_TYPE_BOOLEAN,
97 .name = "Auto White Balance",
104 .id = V4L2_CID_EXPOSURE,
105 .type = V4L2_CTRL_TYPE_INTEGER,
106 .name = "Shutter Speed (Exposure)",
110 .default_value = 200,
113 .id = V4L2_CID_AUTOGAIN,
114 .type = V4L2_CTRL_TYPE_BOOLEAN,
115 .name = "Auto Gain Enabled",
123 .type = V4L2_CTRL_TYPE_INTEGER,
124 .name = "Gain Level",
131 .id = V4L2_CID_PRIVATE_SAVE_USER,
132 .type = V4L2_CTRL_TYPE_BUTTON,
133 .name = "Save User Settings",
140 .id = V4L2_CID_PRIVATE_RESTORE_USER,
141 .type = V4L2_CTRL_TYPE_BUTTON,
142 .name = "Restore User Settings",
149 .id = V4L2_CID_PRIVATE_RESTORE_FACTORY,
150 .type = V4L2_CTRL_TYPE_BUTTON,
151 .name = "Restore Factory Settings",
158 .id = V4L2_CID_PRIVATE_COLOUR_MODE,
159 .type = V4L2_CTRL_TYPE_BOOLEAN,
160 .name = "Colour mode",
167 .id = V4L2_CID_PRIVATE_AUTOCONTOUR,
168 .type = V4L2_CTRL_TYPE_BOOLEAN,
169 .name = "Auto contour",
176 .id = V4L2_CID_PRIVATE_CONTOUR,
177 .type = V4L2_CTRL_TYPE_INTEGER,
185 .id = V4L2_CID_PRIVATE_BACKLIGHT,
186 .type = V4L2_CTRL_TYPE_BOOLEAN,
187 .name = "Backlight compensation",
194 .id = V4L2_CID_PRIVATE_FLICKERLESS,
195 .type = V4L2_CTRL_TYPE_BOOLEAN,
196 .name = "Flickerless",
203 .id = V4L2_CID_PRIVATE_NOISE_REDUCTION,
204 .type = V4L2_CTRL_TYPE_INTEGER,
205 .name = "Noise reduction",
214 /* In 2.6.16-rc1 v4l_printk_ioctl is not defined but exported */
215 extern void v4l_printk_ioctl(unsigned int cmd);
218 static void pwc_vidioc_fill_fmt(const struct pwc_device *pdev, struct v4l2_format *f)
220 memset(&f->fmt.pix, 0, sizeof(struct v4l2_pix_format));
221 f->fmt.pix.width = pdev->view.x;
222 f->fmt.pix.height = pdev->view.y;
223 f->fmt.pix.field = V4L2_FIELD_NONE;
224 if (pdev->vpalette == VIDEO_PALETTE_YUV420P) {
225 f->fmt.pix.pixelformat = V4L2_PIX_FMT_YUV420;
226 f->fmt.pix.bytesperline = (f->fmt.pix.width * 3)/2;
227 f->fmt.pix.sizeimage = f->fmt.pix.height * f->fmt.pix.bytesperline;
229 /* vbandlength contains 4 lines ... */
230 f->fmt.pix.bytesperline = pdev->vbandlength/4;
231 f->fmt.pix.sizeimage = pdev->frame_size + sizeof(struct pwc_raw_frame);
232 if (DEVICE_USE_CODEC1(pdev->type))
233 f->fmt.pix.pixelformat = V4L2_PIX_FMT_PWC1;
235 f->fmt.pix.pixelformat = V4L2_PIX_FMT_PWC2;
237 PWC_DEBUG_IOCTL("pwc_vidioc_fill_fmt() "
238 "width=%d, height=%d, bytesperline=%d, sizeimage=%d, pixelformat=%c%c%c%c\n",
241 f->fmt.pix.bytesperline,
242 f->fmt.pix.sizeimage,
243 (f->fmt.pix.pixelformat)&255,
244 (f->fmt.pix.pixelformat>>8)&255,
245 (f->fmt.pix.pixelformat>>16)&255,
246 (f->fmt.pix.pixelformat>>24)&255);
249 /* ioctl(VIDIOC_TRY_FMT) */
250 static int pwc_vidioc_try_fmt(struct pwc_device *pdev, struct v4l2_format *f)
252 if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
253 PWC_DEBUG_IOCTL("Bad video type must be V4L2_BUF_TYPE_VIDEO_CAPTURE\n");
257 switch (f->fmt.pix.pixelformat) {
258 case V4L2_PIX_FMT_YUV420:
260 case V4L2_PIX_FMT_PWC1:
261 if (DEVICE_USE_CODEC23(pdev->type)) {
262 PWC_DEBUG_IOCTL("codec1 is only supported for old pwc webcam\n");
266 case V4L2_PIX_FMT_PWC2:
267 if (DEVICE_USE_CODEC1(pdev->type)) {
268 PWC_DEBUG_IOCTL("codec23 is only supported for new pwc webcam\n");
273 PWC_DEBUG_IOCTL("Unsupported pixel format\n");
278 if (f->fmt.pix.width > pdev->view_max.x)
279 f->fmt.pix.width = pdev->view_max.x;
280 else if (f->fmt.pix.width < pdev->view_min.x)
281 f->fmt.pix.width = pdev->view_min.x;
283 if (f->fmt.pix.height > pdev->view_max.y)
284 f->fmt.pix.height = pdev->view_max.y;
285 else if (f->fmt.pix.height < pdev->view_min.y)
286 f->fmt.pix.height = pdev->view_min.y;
291 /* ioctl(VIDIOC_SET_FMT) */
292 static int pwc_vidioc_set_fmt(struct pwc_device *pdev, struct v4l2_format *f)
294 int ret, fps, snapshot, compression, pixelformat;
296 ret = pwc_vidioc_try_fmt(pdev, f);
300 pixelformat = f->fmt.pix.pixelformat;
301 compression = pdev->vcompression;
304 if (f->fmt.pix.priv) {
305 compression = (f->fmt.pix.priv & PWC_QLT_MASK) >> PWC_QLT_SHIFT;
306 snapshot = !!(f->fmt.pix.priv & PWC_FPS_SNAPSHOT);
307 fps = (f->fmt.pix.priv & PWC_FPS_FRMASK) >> PWC_FPS_SHIFT;
312 if (pixelformat == V4L2_PIX_FMT_YUV420)
313 pdev->vpalette = VIDEO_PALETTE_YUV420P;
315 pdev->vpalette = VIDEO_PALETTE_RAW;
317 PWC_DEBUG_IOCTL("Try to change format to: width=%d height=%d fps=%d "
318 "compression=%d snapshot=%d format=%c%c%c%c\n",
319 f->fmt.pix.width, f->fmt.pix.height, fps,
320 compression, snapshot,
322 (pixelformat>>8)&255,
323 (pixelformat>>16)&255,
324 (pixelformat>>24)&255);
326 ret = pwc_try_video_mode(pdev,
333 PWC_DEBUG_IOCTL("pwc_try_video_mode(), return=%d\n", ret);
338 pwc_vidioc_fill_fmt(pdev, f);
344 int pwc_video_do_ioctl(struct inode *inode, struct file *file,
345 unsigned int cmd, void *arg)
347 struct video_device *vdev = video_devdata(file);
348 struct pwc_device *pdev;
349 DECLARE_WAITQUEUE(wait, current);
358 if (PWC_DEBUG_LEVEL_IOCTL & pwc_trace)
359 v4l_printk_ioctl(cmd);
364 /* Query cabapilities */
367 struct video_capability *caps = arg;
369 strcpy(caps->name, vdev->name);
370 caps->type = VID_TYPE_CAPTURE;
373 caps->minwidth = pdev->view_min.x;
374 caps->minheight = pdev->view_min.y;
375 caps->maxwidth = pdev->view_max.x;
376 caps->maxheight = pdev->view_max.y;
380 /* Channel functions (simulate 1 channel) */
383 struct video_channel *v = arg;
389 v->type = VIDEO_TYPE_CAMERA;
390 strcpy(v->name, "Webcam");
396 /* The spec says the argument is an integer, but
397 the bttv driver uses a video_channel arg, which
398 makes sense becasue it also has the norm flag.
400 struct video_channel *v = arg;
407 /* Picture functions; contrast etc. */
410 struct video_picture *p = arg;
413 val = pwc_get_brightness(pdev);
415 p->brightness = (val<<9);
417 p->brightness = 0xffff;
418 val = pwc_get_contrast(pdev);
420 p->contrast = (val<<10);
422 p->contrast = 0xffff;
423 /* Gamma, Whiteness, what's the difference? :) */
424 val = pwc_get_gamma(pdev);
426 p->whiteness = (val<<11);
428 p->whiteness = 0xffff;
429 if (pwc_get_saturation(pdev, &val)<0)
432 p->colour = 32768 + val * 327;
434 p->palette = pdev->vpalette;
435 p->hue = 0xFFFF; /* N/A */
441 struct video_picture *p = arg;
443 * FIXME: Suppose we are mid read
444 ANSWER: No problem: the firmware of the camera
445 can handle brightness/contrast/etc
446 changes at _any_ time, and the palette
447 is used exactly once in the uncompress
450 pwc_set_brightness(pdev, p->brightness);
451 pwc_set_contrast(pdev, p->contrast);
452 pwc_set_gamma(pdev, p->whiteness);
453 pwc_set_saturation(pdev, (p->colour-32768)/327);
454 if (p->palette && p->palette != pdev->vpalette) {
455 switch (p->palette) {
456 case VIDEO_PALETTE_YUV420P:
457 case VIDEO_PALETTE_RAW:
458 pdev->vpalette = p->palette;
459 return pwc_try_video_mode(pdev, pdev->image.x, pdev->image.y, pdev->vframes, pdev->vcompression, pdev->vsnapshot);
469 /* Window/size parameters */
472 struct video_window *vw = arg;
476 vw->width = pdev->view.x;
477 vw->height = pdev->view.y;
479 vw->flags = (pdev->vframes << PWC_FPS_SHIFT) |
480 (pdev->vsnapshot ? PWC_FPS_SNAPSHOT : 0);
486 struct video_window *vw = arg;
487 int fps, snapshot, ret;
489 fps = (vw->flags & PWC_FPS_FRMASK) >> PWC_FPS_SHIFT;
490 snapshot = vw->flags & PWC_FPS_SNAPSHOT;
493 if (pdev->view.x == vw->width && pdev->view.y && fps == pdev->vframes && snapshot == pdev->vsnapshot)
495 ret = pwc_try_video_mode(pdev, vw->width, vw->height, fps, pdev->vcompression, snapshot);
501 /* We don't have overlay support (yet) */
504 struct video_buffer *vb = arg;
506 memset(vb,0,sizeof(*vb));
510 /* mmap() functions */
513 /* Tell the user program how much memory is needed for a mmap() */
514 struct video_mbuf *vm = arg;
517 memset(vm, 0, sizeof(*vm));
518 vm->size = pwc_mbufs * pdev->len_per_image;
519 vm->frames = pwc_mbufs; /* double buffering should be enough for most applications */
520 for (i = 0; i < pwc_mbufs; i++)
521 vm->offsets[i] = i * pdev->len_per_image;
527 /* Start capture into a given image buffer (called 'frame' in video_mmap structure) */
528 struct video_mmap *vm = arg;
530 PWC_DEBUG_READ("VIDIOCMCAPTURE: %dx%d, frame %d, format %d\n", vm->width, vm->height, vm->frame, vm->format);
531 if (vm->frame < 0 || vm->frame >= pwc_mbufs)
534 /* xawtv is nasty. It probes the available palettes
535 by setting a very small image size and trying
536 various palettes... The driver doesn't support
537 such small images, so I'm working around it.
543 case VIDEO_PALETTE_YUV420P:
544 case VIDEO_PALETTE_RAW:
552 if ((vm->width != pdev->view.x || vm->height != pdev->view.y) &&
553 (vm->width >= pdev->view_min.x && vm->height >= pdev->view_min.y)) {
556 PWC_DEBUG_OPEN("VIDIOCMCAPTURE: changing size to please xawtv :-(.\n");
557 ret = pwc_try_video_mode(pdev, vm->width, vm->height, pdev->vframes, pdev->vcompression, pdev->vsnapshot);
560 } /* ... size mismatch */
562 /* FIXME: should we lock here? */
563 if (pdev->image_used[vm->frame])
564 return -EBUSY; /* buffer wasn't available. Bummer */
565 pdev->image_used[vm->frame] = 1;
567 /* Okay, we're done here. In the SYNC call we wait until a
568 frame comes available, then expand image into the given
570 In contrast to the CPiA cam the Philips cams deliver a
571 constant stream, almost like a grabber card. Also,
572 we have separate buffers for the rawdata and the image,
573 meaning we can nearly always expand into the requested buffer.
575 PWC_DEBUG_READ("VIDIOCMCAPTURE done.\n");
581 /* The doc says: "Whenever a buffer is used it should
582 call VIDIOCSYNC to free this frame up and continue."
584 The only odd thing about this whole procedure is
585 that MCAPTURE flags the buffer as "in use", and
586 SYNC immediately unmarks it, while it isn't
587 after SYNC that you know that the buffer actually
588 got filled! So you better not start a CAPTURE in
589 the same frame immediately (use double buffering).
590 This is not a problem for this cam, since it has
591 extra intermediate buffers, but a hardware
592 grabber card will then overwrite the buffer
598 PWC_DEBUG_READ("VIDIOCSYNC called (%d).\n", *mbuf);
601 if (*mbuf < 0 || *mbuf >= pwc_mbufs)
603 /* check if this buffer was requested anyway */
604 if (pdev->image_used[*mbuf] == 0)
607 /* Add ourselves to the frame wait-queue.
609 FIXME: needs auditing for safety.
610 QUESTION: In what respect? I think that using the
613 add_wait_queue(&pdev->frameq, &wait);
614 while (pdev->full_frames == NULL) {
615 /* Check for unplugged/etc. here */
616 if (pdev->error_status) {
617 remove_wait_queue(&pdev->frameq, &wait);
618 set_current_state(TASK_RUNNING);
619 return -pdev->error_status;
622 if (signal_pending(current)) {
623 remove_wait_queue(&pdev->frameq, &wait);
624 set_current_state(TASK_RUNNING);
628 set_current_state(TASK_INTERRUPTIBLE);
630 remove_wait_queue(&pdev->frameq, &wait);
631 set_current_state(TASK_RUNNING);
633 /* The frame is ready. Expand in the image buffer
634 requested by the user. I don't care if you
635 mmap() 5 buffers and request data in this order:
636 buffer 4 2 3 0 1 2 3 0 4 3 1 . . .
637 Grabber hardware may not be so forgiving.
639 PWC_DEBUG_READ("VIDIOCSYNC: frame ready.\n");
640 pdev->fill_image = *mbuf; /* tell in which buffer we want the image to be expanded */
641 /* Decompress, etc */
642 ret = pwc_handle_frame(pdev);
643 pdev->image_used[*mbuf] = 0;
651 struct video_audio *v = arg;
653 strcpy(v->name, "Microphone");
654 v->audio = -1; /* unknown audio minor */
656 v->mode = VIDEO_SOUND_MONO;
667 /* Dummy: nothing can be set */
673 struct video_unit *vu = arg;
675 vu->video = pdev->vdev->minor & 0x3F;
676 vu->audio = -1; /* not known yet */
684 case VIDIOC_QUERYCAP:
686 struct v4l2_capability *cap = arg;
688 PWC_DEBUG_IOCTL("ioctl(VIDIOC_QUERYCAP) This application "\
689 "try to use the v4l2 layer\n");
690 strcpy(cap->driver,PWC_NAME);
691 strlcpy(cap->card, vdev->name, sizeof(cap->card));
692 usb_make_path(pdev->udev,cap->bus_info,sizeof(cap->bus_info));
693 cap->version = PWC_VERSION_CODE;
695 V4L2_CAP_VIDEO_CAPTURE |
701 case VIDIOC_ENUMINPUT:
703 struct v4l2_input *i = arg;
705 if ( i->index ) /* Only one INPUT is supported */
708 memset(i, 0, sizeof(struct v4l2_input));
709 strcpy(i->name, "usb");
716 *i = 0; /* Only one INPUT is supported */
723 if ( *i ) { /* Only one INPUT is supported */
724 PWC_DEBUG_IOCTL("Only one input source is"\
725 " supported with this webcam.\n");
732 case VIDIOC_QUERYCTRL:
734 struct v4l2_queryctrl *c = arg;
737 PWC_DEBUG_IOCTL("ioctl(VIDIOC_QUERYCTRL) query id=%d\n", c->id);
738 for (i=0; i<sizeof(pwc_controls)/sizeof(struct v4l2_queryctrl); i++) {
739 if (pwc_controls[i].id == c->id) {
740 PWC_DEBUG_IOCTL("ioctl(VIDIOC_QUERYCTRL) found\n");
741 memcpy(c,&pwc_controls[i],sizeof(struct v4l2_queryctrl));
745 PWC_DEBUG_IOCTL("ioctl(VIDIOC_QUERYCTRL) not found\n");
751 struct v4l2_control *c = arg;
756 case V4L2_CID_BRIGHTNESS:
757 c->value = pwc_get_brightness(pdev);
761 case V4L2_CID_CONTRAST:
762 c->value = pwc_get_contrast(pdev);
766 case V4L2_CID_SATURATION:
767 ret = pwc_get_saturation(pdev, &c->value);
772 c->value = pwc_get_gamma(pdev);
776 case V4L2_CID_RED_BALANCE:
777 ret = pwc_get_red_gain(pdev, &c->value);
782 case V4L2_CID_BLUE_BALANCE:
783 ret = pwc_get_blue_gain(pdev, &c->value);
788 case V4L2_CID_AUTO_WHITE_BALANCE:
789 ret = pwc_get_awb(pdev);
792 c->value = (ret == PWC_WB_MANUAL)?0:1;
795 ret = pwc_get_agc(pdev, &c->value);
800 case V4L2_CID_AUTOGAIN:
801 ret = pwc_get_agc(pdev, &c->value);
804 c->value = (c->value < 0)?1:0;
806 case V4L2_CID_EXPOSURE:
807 ret = pwc_get_shutter_speed(pdev, &c->value);
811 case V4L2_CID_PRIVATE_COLOUR_MODE:
812 ret = pwc_get_colour_mode(pdev, &c->value);
816 case V4L2_CID_PRIVATE_AUTOCONTOUR:
817 ret = pwc_get_contour(pdev, &c->value);
820 c->value=(c->value == -1?1:0);
822 case V4L2_CID_PRIVATE_CONTOUR:
823 ret = pwc_get_contour(pdev, &c->value);
828 case V4L2_CID_PRIVATE_BACKLIGHT:
829 ret = pwc_get_backlight(pdev, &c->value);
833 case V4L2_CID_PRIVATE_FLICKERLESS:
834 ret = pwc_get_flicker(pdev, &c->value);
837 c->value=(c->value?1:0);
839 case V4L2_CID_PRIVATE_NOISE_REDUCTION:
840 ret = pwc_get_dynamic_noise(pdev, &c->value);
845 case V4L2_CID_PRIVATE_SAVE_USER:
846 case V4L2_CID_PRIVATE_RESTORE_USER:
847 case V4L2_CID_PRIVATE_RESTORE_FACTORY:
854 struct v4l2_control *c = arg;
859 case V4L2_CID_BRIGHTNESS:
861 ret = pwc_set_brightness(pdev, c->value);
865 case V4L2_CID_CONTRAST:
867 ret = pwc_set_contrast(pdev, c->value);
871 case V4L2_CID_SATURATION:
872 ret = pwc_set_saturation(pdev, c->value);
878 ret = pwc_set_gamma(pdev, c->value);
882 case V4L2_CID_RED_BALANCE:
884 ret = pwc_set_red_gain(pdev, c->value);
888 case V4L2_CID_BLUE_BALANCE:
890 ret = pwc_set_blue_gain(pdev, c->value);
894 case V4L2_CID_AUTO_WHITE_BALANCE:
895 c->value = (c->value == 0)?PWC_WB_MANUAL:PWC_WB_AUTO;
896 ret = pwc_set_awb(pdev, c->value);
900 case V4L2_CID_EXPOSURE:
902 ret = pwc_set_shutter_speed(pdev, c->value?0:1, c->value);
906 case V4L2_CID_AUTOGAIN:
907 /* autogain off means nothing without a gain */
910 ret = pwc_set_agc(pdev, c->value, 0);
916 ret = pwc_set_agc(pdev, 0, c->value);
920 case V4L2_CID_PRIVATE_SAVE_USER:
921 if (pwc_save_user(pdev))
924 case V4L2_CID_PRIVATE_RESTORE_USER:
925 if (pwc_restore_user(pdev))
928 case V4L2_CID_PRIVATE_RESTORE_FACTORY:
929 if (pwc_restore_factory(pdev))
932 case V4L2_CID_PRIVATE_COLOUR_MODE:
933 ret = pwc_set_colour_mode(pdev, c->value);
937 case V4L2_CID_PRIVATE_AUTOCONTOUR:
938 c->value=(c->value == 1)?-1:0;
939 ret = pwc_set_contour(pdev, c->value);
943 case V4L2_CID_PRIVATE_CONTOUR:
945 ret = pwc_set_contour(pdev, c->value);
949 case V4L2_CID_PRIVATE_BACKLIGHT:
950 ret = pwc_set_backlight(pdev, c->value);
954 case V4L2_CID_PRIVATE_FLICKERLESS:
955 ret = pwc_set_flicker(pdev, c->value);
958 case V4L2_CID_PRIVATE_NOISE_REDUCTION:
959 ret = pwc_set_dynamic_noise(pdev, c->value);
968 case VIDIOC_ENUM_FMT:
970 struct v4l2_fmtdesc *f = arg;
973 if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
976 /* We only support two format: the raw format, and YUV */
978 memset(f,0,sizeof(struct v4l2_fmtdesc));
979 f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
985 f->pixelformat = pdev->type<=646?V4L2_PIX_FMT_PWC1:V4L2_PIX_FMT_PWC2;
986 f->flags = V4L2_FMT_FLAG_COMPRESSED;
987 strlcpy(f->description,"Raw Philips Webcam",sizeof(f->description));
990 f->pixelformat = V4L2_PIX_FMT_YUV420;
991 strlcpy(f->description,"4:2:0, planar, Y-Cb-Cr",sizeof(f->description));
1001 struct v4l2_format *f = arg;
1003 PWC_DEBUG_IOCTL("ioctl(VIDIOC_G_FMT) return size %dx%d\n",pdev->image.x,pdev->image.y);
1004 if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
1007 pwc_vidioc_fill_fmt(pdev, f);
1012 case VIDIOC_TRY_FMT:
1013 return pwc_vidioc_try_fmt(pdev, arg);
1016 return pwc_vidioc_set_fmt(pdev, arg);
1020 v4l2_std_id *std = arg;
1021 *std = V4L2_STD_UNKNOWN;
1027 v4l2_std_id *std = arg;
1028 if (*std != V4L2_STD_UNKNOWN)
1033 case VIDIOC_ENUMSTD:
1035 struct v4l2_standard *std = arg;
1036 if (std->index != 0)
1038 std->id = V4L2_STD_UNKNOWN;
1039 strncpy(std->name, "webcam", sizeof(std->name));
1043 case VIDIOC_REQBUFS:
1045 struct v4l2_requestbuffers *rb = arg;
1048 PWC_DEBUG_IOCTL("ioctl(VIDIOC_REQBUFS) count=%d\n",rb->count);
1049 if (rb->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
1051 if (rb->memory != V4L2_MEMORY_MMAP)
1054 nbuffers = rb->count;
1057 else if (nbuffers > pwc_mbufs)
1058 nbuffers = pwc_mbufs;
1059 /* Force to use our # of buffers */
1060 rb->count = pwc_mbufs;
1064 case VIDIOC_QUERYBUF:
1066 struct v4l2_buffer *buf = arg;
1069 PWC_DEBUG_IOCTL("ioctl(VIDIOC_QUERYBUF) index=%d\n",buf->index);
1070 if (buf->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
1071 PWC_DEBUG_IOCTL("ioctl(VIDIOC_QUERYBUF) Bad type\n");
1074 if (buf->memory != V4L2_MEMORY_MMAP) {
1075 PWC_DEBUG_IOCTL("ioctl(VIDIOC_QUERYBUF) Bad memory type\n");
1079 if (index < 0 || index >= pwc_mbufs) {
1080 PWC_DEBUG_IOCTL("ioctl(VIDIOC_QUERYBUF) Bad index %d\n", buf->index);
1084 memset(buf, 0, sizeof(struct v4l2_buffer));
1085 buf->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1087 buf->m.offset = index * pdev->len_per_image;
1088 if (pdev->vpalette == VIDEO_PALETTE_RAW)
1089 buf->bytesused = pdev->frame_size + sizeof(struct pwc_raw_frame);
1091 buf->bytesused = pdev->view.size;
1092 buf->field = V4L2_FIELD_NONE;
1093 buf->memory = V4L2_MEMORY_MMAP;
1094 //buf->flags = V4L2_BUF_FLAG_MAPPED;
1095 buf->length = pdev->len_per_image;
1097 PWC_DEBUG_READ("VIDIOC_QUERYBUF: index=%d\n",buf->index);
1098 PWC_DEBUG_READ("VIDIOC_QUERYBUF: m.offset=%d\n",buf->m.offset);
1099 PWC_DEBUG_READ("VIDIOC_QUERYBUF: bytesused=%d\n",buf->bytesused);
1106 struct v4l2_buffer *buf = arg;
1108 PWC_DEBUG_IOCTL("ioctl(VIDIOC_QBUF) index=%d\n",buf->index);
1109 if (buf->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
1111 if (buf->memory != V4L2_MEMORY_MMAP)
1113 if (buf->index < 0 || buf->index >= pwc_mbufs)
1116 buf->flags |= V4L2_BUF_FLAG_QUEUED;
1117 buf->flags &= ~V4L2_BUF_FLAG_DONE;
1124 struct v4l2_buffer *buf = arg;
1127 PWC_DEBUG_IOCTL("ioctl(VIDIOC_DQBUF)\n");
1129 if (buf->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
1132 /* Add ourselves to the frame wait-queue.
1134 FIXME: needs auditing for safety.
1135 QUESTION: In what respect? I think that using the
1138 add_wait_queue(&pdev->frameq, &wait);
1139 while (pdev->full_frames == NULL) {
1140 if (pdev->error_status) {
1141 remove_wait_queue(&pdev->frameq, &wait);
1142 set_current_state(TASK_RUNNING);
1143 return -pdev->error_status;
1146 if (signal_pending(current)) {
1147 remove_wait_queue(&pdev->frameq, &wait);
1148 set_current_state(TASK_RUNNING);
1149 return -ERESTARTSYS;
1152 set_current_state(TASK_INTERRUPTIBLE);
1154 remove_wait_queue(&pdev->frameq, &wait);
1155 set_current_state(TASK_RUNNING);
1157 PWC_DEBUG_IOCTL("VIDIOC_DQBUF: frame ready.\n");
1158 /* Decompress data in pdev->images[pdev->fill_image] */
1159 ret = pwc_handle_frame(pdev);
1162 PWC_DEBUG_IOCTL("VIDIOC_DQBUF: after pwc_handle_frame\n");
1164 buf->index = pdev->fill_image;
1165 if (pdev->vpalette == VIDEO_PALETTE_RAW)
1166 buf->bytesused = pdev->frame_size + sizeof(struct pwc_raw_frame);
1168 buf->bytesused = pdev->view.size;
1169 buf->flags = V4L2_BUF_FLAG_MAPPED;
1170 buf->field = V4L2_FIELD_NONE;
1171 do_gettimeofday(&buf->timestamp);
1173 buf->memory = V4L2_MEMORY_MMAP;
1174 buf->m.offset = pdev->fill_image * pdev->len_per_image;
1175 buf->length = buf->bytesused;
1176 pwc_next_image(pdev);
1178 PWC_DEBUG_IOCTL("VIDIOC_DQBUF: buf->index=%d\n",buf->index);
1179 PWC_DEBUG_IOCTL("VIDIOC_DQBUF: buf->length=%d\n",buf->length);
1180 PWC_DEBUG_IOCTL("VIDIOC_DQBUF: m.offset=%d\n",buf->m.offset);
1181 PWC_DEBUG_IOCTL("VIDIOC_DQBUF: bytesused=%d\n",buf->bytesused);
1182 PWC_DEBUG_IOCTL("VIDIOC_DQBUF: leaving\n");
1187 case VIDIOC_STREAMON:
1189 /* WARNING: pwc_try_video_mode() called pwc_isoc_init */
1190 pwc_isoc_init(pdev);
1194 case VIDIOC_STREAMOFF:
1196 pwc_isoc_cleanup(pdev);
1201 return pwc_ioctl(pdev, cmd, arg);
1206 /* vim: set cino= formatoptions=croql cindent shiftwidth=8 tabstop=8: */