📄 v4l1-compat.c
字号:
struct video_channel *chan = arg; memset(&input2,0,sizeof(input2)); input2.index = chan->channel; err = drv(inode, file, VIDIOC_ENUMINPUT, &input2); if (err < 0) { dprintk("VIDIOCGCHAN / VIDIOC_ENUMINPUT: " "channel=%d err=%d\n",chan->channel,err); break; } chan->channel = input2.index; memcpy(chan->name, input2.name, min(sizeof(chan->name), sizeof(input2.name))); chan->name[sizeof(chan->name) - 1] = 0; chan->tuners = (input2.type == V4L2_INPUT_TYPE_TUNER) ? 1 : 0; chan->flags = (chan->tuners) ? VIDEO_VC_TUNER : 0; switch (input2.type) { case V4L2_INPUT_TYPE_TUNER: chan->type = VIDEO_TYPE_TV; break; default: case V4L2_INPUT_TYPE_CAMERA: chan->type = VIDEO_TYPE_CAMERA; break; } chan->norm = 0; err = drv(inode, file, VIDIOC_G_STD, &sid); if (err < 0) dprintk("VIDIOCGCHAN / VIDIOC_G_STD: %d\n",err); if (err == 0) { if (sid & V4L2_STD_PAL) chan->norm = VIDEO_MODE_PAL; if (sid & V4L2_STD_NTSC) chan->norm = VIDEO_MODE_NTSC; if (sid & V4L2_STD_SECAM) chan->norm = VIDEO_MODE_SECAM; } break; } case VIDIOCSCHAN: /* set input */ { struct video_channel *chan = arg; sid = 0; err = drv(inode, file, VIDIOC_S_INPUT, &chan->channel); if (err < 0) dprintk("VIDIOCSCHAN / VIDIOC_S_INPUT: %d\n",err); switch (chan->norm) { case VIDEO_MODE_PAL: sid = V4L2_STD_PAL; break; case VIDEO_MODE_NTSC: sid = V4L2_STD_NTSC; break; case VIDEO_MODE_SECAM: sid = V4L2_STD_SECAM; break; } if (0 != sid) { err = drv(inode, file, VIDIOC_S_STD, &sid); if (err < 0) dprintk("VIDIOCSCHAN / VIDIOC_S_STD: %d\n",err); } break; } case VIDIOCGPICT: /* get tone controls & partial capture format */ { struct video_picture *pict = arg; pict->brightness = get_v4l_control(inode, file, V4L2_CID_BRIGHTNESS,drv); pict->hue = get_v4l_control(inode, file, V4L2_CID_HUE, drv); pict->contrast = get_v4l_control(inode, file, V4L2_CID_CONTRAST, drv); pict->colour = get_v4l_control(inode, file, V4L2_CID_SATURATION, drv); pict->whiteness = get_v4l_control(inode, file, V4L2_CID_WHITENESS, drv); fmt2 = kmalloc(sizeof(*fmt2),GFP_KERNEL); memset(fmt2,0,sizeof(*fmt2)); fmt2->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; err = drv(inode, file, VIDIOC_G_FMT, fmt2); if (err < 0) { dprintk("VIDIOCGPICT / VIDIOC_G_FMT: %d\n",err); break; }#if 0 /* FIXME */ pict->depth = fmt2->fmt.pix.depth;#endif pict->palette = pixelformat_to_palette( fmt2->fmt.pix.pixelformat); break; } case VIDIOCSPICT: /* set tone controls & partial capture format */ { struct video_picture *pict = arg; set_v4l_control(inode, file, V4L2_CID_BRIGHTNESS, pict->brightness, drv); set_v4l_control(inode, file, V4L2_CID_HUE, pict->hue, drv); set_v4l_control(inode, file, V4L2_CID_CONTRAST, pict->contrast, drv); set_v4l_control(inode, file, V4L2_CID_SATURATION, pict->colour, drv); set_v4l_control(inode, file, V4L2_CID_WHITENESS, pict->whiteness, drv); fmt2 = kmalloc(sizeof(*fmt2),GFP_KERNEL); memset(fmt2,0,sizeof(*fmt2)); fmt2->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; err = drv(inode, file, VIDIOC_G_FMT, fmt2); if (err < 0) dprintk("VIDIOCSPICT / VIDIOC_G_FMT: %d\n",err); if (fmt2->fmt.pix.pixelformat != palette_to_pixelformat(pict->palette)) { fmt2->fmt.pix.pixelformat = palette_to_pixelformat( pict->palette); err = drv(inode, file, VIDIOC_S_FMT, fmt2); if (err < 0) dprintk("VIDIOCSPICT / VIDIOC_S_FMT: %d\n",err); } err = drv(inode, file, VIDIOC_G_FBUF, &fbuf2); if (err < 0) dprintk("VIDIOCSPICT / VIDIOC_G_FBUF: %d\n",err); if (fbuf2.fmt.pixelformat != palette_to_pixelformat(pict->palette)) { fbuf2.fmt.pixelformat = palette_to_pixelformat( pict->palette); err = drv(inode, file, VIDIOC_S_FBUF, &fbuf2); if (err < 0) dprintk("VIDIOCSPICT / VIDIOC_S_FBUF: %d\n",err); err = 0; /* likely fails for non-root */ } break; } case VIDIOCGTUNER: /* get tuner information */ { struct video_tuner *tun = arg; memset(&tun2,0,sizeof(tun2)); err = drv(inode, file, VIDIOC_G_TUNER, &tun2); if (err < 0) { dprintk("VIDIOCGTUNER / VIDIOC_G_TUNER: %d\n",err); break; } memcpy(tun->name, tun2.name, min(sizeof(tun->name), sizeof(tun2.name))); tun->name[sizeof(tun->name) - 1] = 0; tun->rangelow = tun2.rangelow; tun->rangehigh = tun2.rangehigh; tun->flags = 0; tun->mode = VIDEO_MODE_AUTO; for (i = 0; i < 64; i++) { memset(&std2,0,sizeof(std2)); std2.index = i; if (0 != drv(inode, file, VIDIOC_ENUMSTD, &std2)) break; if (std2.id & V4L2_STD_PAL) tun->flags |= VIDEO_TUNER_PAL; if (std2.id & V4L2_STD_NTSC) tun->flags |= VIDEO_TUNER_NTSC; if (std2.id & V4L2_STD_SECAM) tun->flags |= VIDEO_TUNER_SECAM; } err = drv(inode, file, VIDIOC_G_STD, &sid); if (err < 0) dprintk("VIDIOCGTUNER / VIDIOC_G_STD: %d\n",err); if (err == 0) { if (sid & V4L2_STD_PAL) tun->mode = VIDEO_MODE_PAL; if (sid & V4L2_STD_NTSC) tun->mode = VIDEO_MODE_NTSC; if (sid & V4L2_STD_SECAM) tun->mode = VIDEO_MODE_SECAM; } if (tun2.capability & V4L2_TUNER_CAP_LOW) tun->flags |= VIDEO_TUNER_LOW; if (tun2.rxsubchans & V4L2_TUNER_SUB_STEREO) tun->flags |= VIDEO_TUNER_STEREO_ON; tun->signal = tun2.signal; break; } case VIDIOCSTUNER: /* select a tuner input */ {#if 0 /* FIXME */ err = drv(inode, file, VIDIOC_S_INPUT, &i); if (err < 0) dprintk("VIDIOCSTUNER / VIDIOC_S_INPUT: %d\n",err);#else err = 0;#endif break; } case VIDIOCGFREQ: /* get frequency */ { int *freq = arg; freq2.tuner = 0; err = drv(inode, file, VIDIOC_G_FREQUENCY, &freq2); if (err < 0) dprintk("VIDIOCGFREQ / VIDIOC_G_FREQUENCY: %d\n",err); if (0 == err) *freq = freq2.frequency; break; } case VIDIOCSFREQ: /* set frequency */ { int *freq = arg; freq2.tuner = 0; drv(inode, file, VIDIOC_G_FREQUENCY, &freq2); freq2.frequency = *freq; err = drv(inode, file, VIDIOC_S_FREQUENCY, &freq2); if (err < 0) dprintk("VIDIOCSFREQ / VIDIOC_S_FREQUENCY: %d\n",err); break; } case VIDIOCGAUDIO: /* get audio properties/controls */ { struct video_audio *aud = arg; err = drv(inode, file, VIDIOC_G_AUDIO, &aud2); if (err < 0) { dprintk("VIDIOCGAUDIO / VIDIOC_G_AUDIO: %d\n",err); break; } 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(inode, file, V4L2_CID_AUDIO_VOLUME, drv); if (i >= 0) { aud->volume = i; aud->flags |= VIDEO_AUDIO_VOLUME; } i = get_v4l_control(inode, file, V4L2_CID_AUDIO_BASS, drv); if (i >= 0) { aud->bass = i; aud->flags |= VIDEO_AUDIO_BASS; } i = get_v4l_control(inode, file, V4L2_CID_AUDIO_TREBLE, drv); if (i >= 0) { aud->treble = i; aud->flags |= VIDEO_AUDIO_TREBLE; } i = get_v4l_control(inode, file, V4L2_CID_AUDIO_BALANCE, drv); if (i >= 0) { aud->balance = i; aud->flags |= VIDEO_AUDIO_BALANCE; } i = get_v4l_control(inode, 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(inode, file, VIDIOC_QUERYCTRL, &qctrl2) == 0 && !(qctrl2.flags & V4L2_CTRL_FLAG_DISABLED)) aud->step = qctrl2.step; aud->mode = 0; err = drv(inode, file, VIDIOC_G_TUNER, &tun2); if (err < 0) { dprintk("VIDIOCGAUDIO / VIDIOC_G_TUNER: %d\n",err); err = 0; break; } 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; break; } case VIDIOCSAUDIO: /* set audio controls */ { struct video_audio *aud = arg; memset(&aud2,0,sizeof(aud2)); memset(&tun2,0,sizeof(tun2)); aud2.index = aud->audio; err = drv(inode, file, VIDIOC_S_AUDIO, &aud2); if (err < 0) { dprintk("VIDIOCSAUDIO / VIDIOC_S_AUDIO: %d\n",err); break; } set_v4l_control(inode, file, V4L2_CID_AUDIO_VOLUME, aud->volume, drv); set_v4l_control(inode, file, V4L2_CID_AUDIO_BASS, aud->bass, drv); set_v4l_control(inode, file, V4L2_CID_AUDIO_TREBLE, aud->treble, drv); set_v4l_control(inode, file, V4L2_CID_AUDIO_BALANCE, aud->balance, drv); set_v4l_control(inode, file, V4L2_CID_AUDIO_MUTE, !!(aud->flags & VIDEO_AUDIO_MUTE), drv); err = drv(inode, 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(inode, file, VIDIOC_S_TUNER, &tun2); if (err < 0) dprintk("VIDIOCSAUDIO / VIDIOC_S_TUNER: %d\n",err); } err = 0; 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 */ { struct video_mmap *mm = arg; fmt2 = kmalloc(sizeof(*fmt2),GFP_KERNEL); memset(&buf2,0,sizeof(buf2)); memset(fmt2,0,sizeof(*fmt2)); fmt2->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; err = drv(inode, file, VIDIOC_G_FMT, fmt2); if (err < 0) { dprintk("VIDIOCMCAPTURE / VIDIOC_G_FMT: %d\n",err); break; } if (mm->width != fmt2->fmt.pix.width || mm->height != fmt2->fmt.pix.height || palette_to_pixelformat(mm->format) != fmt2->fmt.pix.pixelformat) {/* New capture format... */ fmt2->fmt.pix.width = mm->width; fmt2->fmt.pix.height = mm->height; fmt2->fmt.pix.pixelformat = palette_to_pixelformat(mm->format); fmt2->fmt.pix.field = V4L2_FIELD_ANY; fmt2->fmt.pix.bytesperline = 0; err = drv(inode, file, VIDIOC_S_FMT, fmt2); if (err < 0) { dprintk("VIDIOCMCAPTURE / VIDIOC_S_FMT: %d\n",err); break; } } buf2.index = mm->frame; buf2.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; err = drv(inode, file, VIDIOC_QUERYBUF, &buf2); if (err < 0) { dprintk("VIDIOCMCAPTURE / VIDIOC_QUERYBUF: %d\n",err); break; } err = drv(inode, file, VIDIOC_QBUF, &buf2); if (err < 0) { dprintk("VIDIOCMCAPTURE / VIDIOC_QBUF: %d\n",err); break; } err = drv(inode, file, VIDIOC_STREAMON, &captype); if (err < 0) dprintk("VIDIOCMCAPTURE / VIDIOC_STREAMON: %d\n",err); break; } case VIDIOCSYNC: /* wait for a frame */ { int *i = arg; buf2.index = *i; buf2.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; err = drv(inode, file, VIDIOC_QUERYBUF, &buf2); if (err < 0) { /* No such buffer */ dprintk("VIDIOCSYNC / VIDIOC_QUERYBUF: %d\n",err); break; } if (!(buf2.flags & V4L2_BUF_FLAG_MAPPED)) { /* Buffer is not mapped */ err = -EINVAL; break; } /* make sure capture actually runs so we don't block forever */ err = drv(inode, file, VIDIOC_STREAMON, &captype); if (err < 0) { dprintk("VIDIOCSYNC / VIDIOC_STREAMON: %d\n",err); break; } /* Loop as long as the buffer is queued, but not done */ while ((buf2.flags & (V4L2_BUF_FLAG_QUEUED | V4L2_BUF_FLAG_DONE)) == V4L2_BUF_FLAG_QUEUED) { err = poll_one(file); if (err < 0 || /* error or sleep was interrupted */ err == 0) /* timeout? Shouldn't occur. */ break; err = drv(inode, file, VIDIOC_QUERYBUF, &buf2); if (err < 0) dprintk("VIDIOCSYNC / VIDIOC_QUERYBUF: %d\n",err); } if (!(buf2.flags & V4L2_BUF_FLAG_DONE)) /* not done */ break; do { err = drv(inode, file, VIDIOC_DQBUF, &buf2); if (err < 0) dprintk("VIDIOCSYNC / VIDIOC_DQBUF: %d\n",err); } while (err == 0 && buf2.index != *i); break; } case VIDIOCGVBIFMT: /* query VBI data capture format */ { struct vbi_format *fmt = arg; fmt2 = kmalloc(sizeof(*fmt2),GFP_KERNEL); memset(fmt2, 0, sizeof(*fmt2)); fmt2->type = V4L2_BUF_TYPE_VBI_CAPTURE; err = drv(inode, file, VIDIOC_G_FMT, fmt2); if (err < 0) { dprintk("VIDIOCGVBIFMT / VIDIOC_G_FMT: %d\n", err); break; } 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; break; } case VIDIOCSVBIFMT: { struct vbi_format *fmt = arg; fmt2 = kmalloc(sizeof(*fmt2),GFP_KERNEL); memset(fmt2, 0, sizeof(*fmt2)); 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(inode, file, VIDIOC_TRY_FMT, fmt2); if (err < 0) { dprintk("VIDIOCSVBIFMT / VIDIOC_TRY_FMT: %d\n", err); break; } if (fmt2->fmt.vbi.samples_per_line != fmt->samples_per_line || fmt2->fmt.vbi.sampling_rate != fmt->sampling_rate || VIDEO_PALETTE_RAW != fmt->sample_format || 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; break; } err = drv(inode, file, VIDIOC_S_FMT, fmt2); if (err < 0) dprintk("VIDIOCSVBIFMT / VIDIOC_S_FMT: %d\n", err); break; } default: err = -ENOIOCTLCMD; break; } if (cap2) kfree(cap2); if (fmt2) kfree(fmt2); 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 + -