📄 v4l1-compat.c
字号:
v4l2_kioctl drv){ int err, i; struct v4l2_queryctrl qctrl2; struct v4l2_audio aud2; struct v4l2_tuner tun2; memset(&aud2, 0, sizeof(aud2)); err = drv(file, VIDIOC_G_AUDIO, &aud2); if (err < 0) { dprintk("VIDIOCGAUDIO / VIDIOC_G_AUDIO: %d\n", err); goto done; } memcpy(aud->name, aud2.name, min(sizeof(aud->name), sizeof(aud2.name))); aud->name[sizeof(aud->name) - 1] = 0; aud->audio = aud2.index; aud->flags = 0; i = get_v4l_control(file, V4L2_CID_AUDIO_VOLUME, drv); if (i >= 0) { aud->volume = i; aud->flags |= VIDEO_AUDIO_VOLUME; } i = get_v4l_control(file, V4L2_CID_AUDIO_BASS, drv); if (i >= 0) { aud->bass = i; aud->flags |= VIDEO_AUDIO_BASS; } i = get_v4l_control(file, V4L2_CID_AUDIO_TREBLE, drv); if (i >= 0) { aud->treble = i; aud->flags |= VIDEO_AUDIO_TREBLE; } i = get_v4l_control(file, V4L2_CID_AUDIO_BALANCE, drv); if (i >= 0) { aud->balance = i; aud->flags |= VIDEO_AUDIO_BALANCE; } i = get_v4l_control(file, V4L2_CID_AUDIO_MUTE, drv); if (i >= 0) { if (i) aud->flags |= VIDEO_AUDIO_MUTE; aud->flags |= VIDEO_AUDIO_MUTABLE; } aud->step = 1; qctrl2.id = V4L2_CID_AUDIO_VOLUME; if (drv(file, VIDIOC_QUERYCTRL, &qctrl2) == 0 && !(qctrl2.flags & V4L2_CTRL_FLAG_DISABLED)) aud->step = qctrl2.step; aud->mode = 0; memset(&tun2, 0, sizeof(tun2)); err = drv(file, VIDIOC_G_TUNER, &tun2); if (err < 0) { dprintk("VIDIOCGAUDIO / VIDIOC_G_TUNER: %d\n", err); err = 0; goto done; } if (tun2.rxsubchans & V4L2_TUNER_SUB_LANG2) aud->mode = VIDEO_SOUND_LANG1 | VIDEO_SOUND_LANG2; else if (tun2.rxsubchans & V4L2_TUNER_SUB_STEREO) aud->mode = VIDEO_SOUND_STEREO; else if (tun2.rxsubchans & V4L2_TUNER_SUB_MONO) aud->mode = VIDEO_SOUND_MONO;done: return err;}static noinline int v4l1_compat_set_audio( struct video_audio *aud, struct file *file, v4l2_kioctl drv){ int err; struct v4l2_audio aud2; struct v4l2_tuner tun2; memset(&aud2, 0, sizeof(aud2)); memset(&tun2, 0, sizeof(tun2)); aud2.index = aud->audio; err = drv(file, VIDIOC_S_AUDIO, &aud2); if (err < 0) { dprintk("VIDIOCSAUDIO / VIDIOC_S_AUDIO: %d\n", err); goto done; } set_v4l_control(file, V4L2_CID_AUDIO_VOLUME, aud->volume, drv); set_v4l_control(file, V4L2_CID_AUDIO_BASS, aud->bass, drv); set_v4l_control(file, V4L2_CID_AUDIO_TREBLE, aud->treble, drv); set_v4l_control(file, V4L2_CID_AUDIO_BALANCE, aud->balance, drv); set_v4l_control(file, V4L2_CID_AUDIO_MUTE, !!(aud->flags & VIDEO_AUDIO_MUTE), drv); err = drv(file, VIDIOC_G_TUNER, &tun2); if (err < 0) dprintk("VIDIOCSAUDIO / VIDIOC_G_TUNER: %d\n", err); if (err == 0) { switch (aud->mode) { default: case VIDEO_SOUND_MONO: case VIDEO_SOUND_LANG1: tun2.audmode = V4L2_TUNER_MODE_MONO; break; case VIDEO_SOUND_STEREO: tun2.audmode = V4L2_TUNER_MODE_STEREO; break; case VIDEO_SOUND_LANG2: tun2.audmode = V4L2_TUNER_MODE_LANG2; break; } err = drv(file, VIDIOC_S_TUNER, &tun2); if (err < 0) dprintk("VIDIOCSAUDIO / VIDIOC_S_TUNER: %d\n", err); } err = 0;done: return err;}static noinline int v4l1_compat_capture_frame( struct video_mmap *mm, struct file *file, v4l2_kioctl drv){ int err; enum v4l2_buf_type captype = V4L2_BUF_TYPE_VIDEO_CAPTURE; struct v4l2_buffer buf; struct v4l2_format *fmt; fmt = kzalloc(sizeof(*fmt), GFP_KERNEL); if (!fmt) { err = -ENOMEM; return err; } memset(&buf, 0, sizeof(buf)); fmt->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; err = drv(file, VIDIOC_G_FMT, fmt); if (err < 0) { dprintk("VIDIOCMCAPTURE / VIDIOC_G_FMT: %d\n", err); goto done; } if (mm->width != fmt->fmt.pix.width || mm->height != fmt->fmt.pix.height || palette_to_pixelformat(mm->format) != fmt->fmt.pix.pixelformat) { /* New capture format... */ fmt->fmt.pix.width = mm->width; fmt->fmt.pix.height = mm->height; fmt->fmt.pix.pixelformat = palette_to_pixelformat(mm->format); fmt->fmt.pix.field = V4L2_FIELD_ANY; fmt->fmt.pix.bytesperline = 0; err = drv(file, VIDIOC_S_FMT, fmt); if (err < 0) { dprintk("VIDIOCMCAPTURE / VIDIOC_S_FMT: %d\n", err); goto done; } } buf.index = mm->frame; buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; err = drv(file, VIDIOC_QUERYBUF, &buf); if (err < 0) { dprintk("VIDIOCMCAPTURE / VIDIOC_QUERYBUF: %d\n", err); goto done; } err = drv(file, VIDIOC_QBUF, &buf); if (err < 0) { dprintk("VIDIOCMCAPTURE / VIDIOC_QBUF: %d\n", err); goto done; } err = drv(file, VIDIOC_STREAMON, &captype); if (err < 0) dprintk("VIDIOCMCAPTURE / VIDIOC_STREAMON: %d\n", err);done: kfree(fmt); return err;}static noinline int v4l1_compat_sync( int *i, struct file *file, v4l2_kioctl drv){ int err; enum v4l2_buf_type captype = V4L2_BUF_TYPE_VIDEO_CAPTURE; struct v4l2_buffer buf; struct poll_wqueues *pwq; memset(&buf, 0, sizeof(buf)); buf.index = *i; buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; err = drv(file, VIDIOC_QUERYBUF, &buf); if (err < 0) { /* No such buffer */ dprintk("VIDIOCSYNC / VIDIOC_QUERYBUF: %d\n", err); goto done; } if (!(buf.flags & V4L2_BUF_FLAG_MAPPED)) { /* Buffer is not mapped */ err = -EINVAL; goto done; } /* make sure capture actually runs so we don't block forever */ err = drv(file, VIDIOC_STREAMON, &captype); if (err < 0) { dprintk("VIDIOCSYNC / VIDIOC_STREAMON: %d\n", err); goto done; } pwq = kmalloc(sizeof(*pwq), GFP_KERNEL); /* Loop as long as the buffer is queued, but not done */ while ((buf.flags & (V4L2_BUF_FLAG_QUEUED | V4L2_BUF_FLAG_DONE)) == V4L2_BUF_FLAG_QUEUED) { err = poll_one(file, pwq); if (err < 0 || /* error or sleep was interrupted */ err == 0) /* timeout? Shouldn't occur. */ break; err = drv(file, VIDIOC_QUERYBUF, &buf); if (err < 0) dprintk("VIDIOCSYNC / VIDIOC_QUERYBUF: %d\n", err); } kfree(pwq); if (!(buf.flags & V4L2_BUF_FLAG_DONE)) /* not done */ goto done; do { err = drv(file, VIDIOC_DQBUF, &buf); if (err < 0) dprintk("VIDIOCSYNC / VIDIOC_DQBUF: %d\n", err); } while (err == 0 && buf.index != *i);done: return err;}static noinline int v4l1_compat_get_vbi_format( struct vbi_format *fmt, struct file *file, v4l2_kioctl drv){ int err; struct v4l2_format *fmt2; fmt2 = kzalloc(sizeof(*fmt2), GFP_KERNEL); if (!fmt2) { err = -ENOMEM; return err; } fmt2->type = V4L2_BUF_TYPE_VBI_CAPTURE; err = drv(file, VIDIOC_G_FMT, fmt2); if (err < 0) { dprintk("VIDIOCGVBIFMT / VIDIOC_G_FMT: %d\n", err); goto done; } if (fmt2->fmt.vbi.sample_format != V4L2_PIX_FMT_GREY) { err = -EINVAL; goto done; } memset(fmt, 0, sizeof(*fmt)); fmt->samples_per_line = fmt2->fmt.vbi.samples_per_line; fmt->sampling_rate = fmt2->fmt.vbi.sampling_rate; fmt->sample_format = VIDEO_PALETTE_RAW; fmt->start[0] = fmt2->fmt.vbi.start[0]; fmt->count[0] = fmt2->fmt.vbi.count[0]; fmt->start[1] = fmt2->fmt.vbi.start[1]; fmt->count[1] = fmt2->fmt.vbi.count[1]; fmt->flags = fmt2->fmt.vbi.flags & 0x03;done: kfree(fmt2); return err;}static noinline int v4l1_compat_set_vbi_format( struct vbi_format *fmt, struct file *file, v4l2_kioctl drv){ int err; struct v4l2_format *fmt2 = NULL; if (VIDEO_PALETTE_RAW != fmt->sample_format) { err = -EINVAL; return err; } fmt2 = kzalloc(sizeof(*fmt2), GFP_KERNEL); if (!fmt2) { err = -ENOMEM; return err; } fmt2->type = V4L2_BUF_TYPE_VBI_CAPTURE; fmt2->fmt.vbi.samples_per_line = fmt->samples_per_line; fmt2->fmt.vbi.sampling_rate = fmt->sampling_rate; fmt2->fmt.vbi.sample_format = V4L2_PIX_FMT_GREY; fmt2->fmt.vbi.start[0] = fmt->start[0]; fmt2->fmt.vbi.count[0] = fmt->count[0]; fmt2->fmt.vbi.start[1] = fmt->start[1]; fmt2->fmt.vbi.count[1] = fmt->count[1]; fmt2->fmt.vbi.flags = fmt->flags; err = drv(file, VIDIOC_TRY_FMT, fmt2); if (err < 0) { dprintk("VIDIOCSVBIFMT / VIDIOC_TRY_FMT: %d\n", err); goto done; } if (fmt2->fmt.vbi.samples_per_line != fmt->samples_per_line || fmt2->fmt.vbi.sampling_rate != fmt->sampling_rate || fmt2->fmt.vbi.sample_format != V4L2_PIX_FMT_GREY || fmt2->fmt.vbi.start[0] != fmt->start[0] || fmt2->fmt.vbi.count[0] != fmt->count[0] || fmt2->fmt.vbi.start[1] != fmt->start[1] || fmt2->fmt.vbi.count[1] != fmt->count[1] || fmt2->fmt.vbi.flags != fmt->flags) { err = -EINVAL; goto done; } err = drv(file, VIDIOC_S_FMT, fmt2); if (err < 0) dprintk("VIDIOCSVBIFMT / VIDIOC_S_FMT: %d\n", err);done: kfree(fmt2); return err;}/* * This function is exported. */intv4l_compat_translate_ioctl(struct file *file, int cmd, void *arg, v4l2_kioctl drv){ int err; switch (cmd) { case VIDIOCGCAP: /* capability */ err = v4l1_compat_get_capabilities(arg, file, drv); break; case VIDIOCGFBUF: /* get frame buffer */ err = v4l1_compat_get_frame_buffer(arg, file, drv); break; case VIDIOCSFBUF: /* set frame buffer */ err = v4l1_compat_set_frame_buffer(arg, file, drv); break; case VIDIOCGWIN: /* get window or capture dimensions */ err = v4l1_compat_get_win_cap_dimensions(arg, file, drv); break; case VIDIOCSWIN: /* set window and/or capture dimensions */ err = v4l1_compat_set_win_cap_dimensions(arg, file, drv); break; case VIDIOCCAPTURE: /* turn on/off preview */ err = v4l1_compat_turn_preview_on_off(arg, file, drv); break; case VIDIOCGCHAN: /* get input information */ err = v4l1_compat_get_input_info(arg, file, drv); break; case VIDIOCSCHAN: /* set input */ err = v4l1_compat_set_input(arg, file, drv); break; case VIDIOCGPICT: /* get tone controls & partial capture format */ err = v4l1_compat_get_picture(arg, file, drv); break; case VIDIOCSPICT: /* set tone controls & partial capture format */ err = v4l1_compat_set_picture(arg, file, drv); break; case VIDIOCGTUNER: /* get tuner information */ err = v4l1_compat_get_tuner(arg, file, drv); break; case VIDIOCSTUNER: /* select a tuner input */ err = v4l1_compat_select_tuner(arg, file, drv); break; case VIDIOCGFREQ: /* get frequency */ err = v4l1_compat_get_frequency(arg, file, drv); break; case VIDIOCSFREQ: /* set frequency */ err = v4l1_compat_set_frequency(arg, file, drv); break; case VIDIOCGAUDIO: /* get audio properties/controls */ err = v4l1_compat_get_audio(arg, file, drv); break; case VIDIOCSAUDIO: /* set audio controls */ err = v4l1_compat_set_audio(arg, file, drv); break;#if 0 case VIDIOCGMBUF: /* v4l2 drivers must implement that themself. The mmap() differences can't be translated fully transparent, thus there is no point to try that */#endif case VIDIOCMCAPTURE: /* capture a frame */ err = v4l1_compat_capture_frame(arg, file, drv); break; case VIDIOCSYNC: /* wait for a frame */ err = v4l1_compat_sync(arg, file, drv); break; case VIDIOCGVBIFMT: /* query VBI data capture format */ err = v4l1_compat_get_vbi_format(arg, file, drv); break; case VIDIOCSVBIFMT: err = v4l1_compat_set_vbi_format(arg, file, drv); break; default: err = -ENOIOCTLCMD; break; } return err;}EXPORT_SYMBOL(v4l_compat_translate_ioctl);/* * Local variables: * c-basic-offset: 8 * End: */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -