v4l2 ioctl框架分析
来源:互联网 发布:滤镜软件原宿风 编辑:程序博客网 时间:2024/06/01 09:42
v4l2的ioctl框架由drivers/media/v4l2-ioctl.c实现
涉及到的结构体:
struct v4l2_ioctl_ops {/* ioctl callbacks *//* VIDIOC_QUERYCAP handler */int (*vidioc_querycap)(struct file *file, void *fh, struct v4l2_capability *cap);/* Priority handling */int (*vidioc_g_priority) (struct file *file, void *fh, enum v4l2_priority *p);int (*vidioc_s_priority) (struct file *file, void *fh, enum v4l2_priority p);/* VIDIOC_ENUM_FMT handlers */int (*vidioc_enum_fmt_vid_cap) (struct file *file, void *fh, struct v4l2_fmtdesc *f);int (*vidioc_enum_fmt_vid_overlay) (struct file *file, void *fh, struct v4l2_fmtdesc *f);int (*vidioc_enum_fmt_vid_out) (struct file *file, void *fh, struct v4l2_fmtdesc *f);int (*vidioc_enum_fmt_vid_cap_mplane)(struct file *file, void *fh, struct v4l2_fmtdesc *f);int (*vidioc_enum_fmt_vid_out_mplane)(struct file *file, void *fh, struct v4l2_fmtdesc *f);int (*vidioc_enum_fmt_type_private)(struct file *file, void *fh, struct v4l2_fmtdesc *f);/* VIDIOC_G_FMT handlers */int (*vidioc_g_fmt_vid_cap) (struct file *file, void *fh,struct v4l2_format *f);int (*vidioc_g_fmt_vid_overlay)(struct file *file, void *fh,struct v4l2_format *f);int (*vidioc_g_fmt_vid_out) (struct file *file, void *fh,struct v4l2_format *f);int (*vidioc_g_fmt_vid_out_overlay)(struct file *file, void *fh,struct v4l2_format *f);int (*vidioc_g_fmt_vbi_cap) (struct file *file, void *fh,struct v4l2_format *f);int (*vidioc_g_fmt_vbi_out) (struct file *file, void *fh,struct v4l2_format *f);int (*vidioc_g_fmt_sliced_vbi_cap)(struct file *file, void *fh,struct v4l2_format *f);int (*vidioc_g_fmt_sliced_vbi_out)(struct file *file, void *fh,struct v4l2_format *f);int (*vidioc_g_fmt_vid_cap_mplane)(struct file *file, void *fh, struct v4l2_format *f);int (*vidioc_g_fmt_vid_out_mplane)(struct file *file, void *fh, struct v4l2_format *f);int (*vidioc_g_fmt_type_private)(struct file *file, void *fh,struct v4l2_format *f);/* VIDIOC_S_FMT handlers */int (*vidioc_s_fmt_vid_cap) (struct file *file, void *fh,struct v4l2_format *f);int (*vidioc_s_fmt_vid_overlay)(struct file *file, void *fh,struct v4l2_format *f);int (*vidioc_s_fmt_vid_out) (struct file *file, void *fh,struct v4l2_format *f);int (*vidioc_s_fmt_vid_out_overlay)(struct file *file, void *fh,struct v4l2_format *f);int (*vidioc_s_fmt_vbi_cap) (struct file *file, void *fh,struct v4l2_format *f);int (*vidioc_s_fmt_vbi_out) (struct file *file, void *fh,struct v4l2_format *f);int (*vidioc_s_fmt_sliced_vbi_cap)(struct file *file, void *fh,struct v4l2_format *f);int (*vidioc_s_fmt_sliced_vbi_out)(struct file *file, void *fh,struct v4l2_format *f);int (*vidioc_s_fmt_vid_cap_mplane)(struct file *file, void *fh, struct v4l2_format *f);int (*vidioc_s_fmt_vid_out_mplane)(struct file *file, void *fh, struct v4l2_format *f);int (*vidioc_s_fmt_type_private)(struct file *file, void *fh,struct v4l2_format *f);/* VIDIOC_TRY_FMT handlers */int (*vidioc_try_fmt_vid_cap) (struct file *file, void *fh, struct v4l2_format *f);int (*vidioc_try_fmt_vid_overlay)(struct file *file, void *fh, struct v4l2_format *f);int (*vidioc_try_fmt_vid_out) (struct file *file, void *fh, struct v4l2_format *f);int (*vidioc_try_fmt_vid_out_overlay)(struct file *file, void *fh, struct v4l2_format *f);int (*vidioc_try_fmt_vbi_cap) (struct file *file, void *fh, struct v4l2_format *f);int (*vidioc_try_fmt_vbi_out) (struct file *file, void *fh, struct v4l2_format *f);int (*vidioc_try_fmt_sliced_vbi_cap)(struct file *file, void *fh, struct v4l2_format *f);int (*vidioc_try_fmt_sliced_vbi_out)(struct file *file, void *fh, struct v4l2_format *f);int (*vidioc_try_fmt_vid_cap_mplane)(struct file *file, void *fh, struct v4l2_format *f);int (*vidioc_try_fmt_vid_out_mplane)(struct file *file, void *fh, struct v4l2_format *f);int (*vidioc_try_fmt_type_private)(struct file *file, void *fh, struct v4l2_format *f);/* Buffer handlers */int (*vidioc_reqbufs) (struct file *file, void *fh, struct v4l2_requestbuffers *b);int (*vidioc_querybuf)(struct file *file, void *fh, struct v4l2_buffer *b);int (*vidioc_qbuf) (struct file *file, void *fh, struct v4l2_buffer *b);int (*vidioc_dqbuf) (struct file *file, void *fh, struct v4l2_buffer *b);int (*vidioc_overlay) (struct file *file, void *fh, unsigned int i);int (*vidioc_g_fbuf) (struct file *file, void *fh,struct v4l2_framebuffer *a);int (*vidioc_s_fbuf) (struct file *file, void *fh,struct v4l2_framebuffer *a);/* Stream on/off */int (*vidioc_streamon) (struct file *file, void *fh, enum v4l2_buf_type i);int (*vidioc_streamoff)(struct file *file, void *fh, enum v4l2_buf_type i);/* Standard handlingENUMSTD is handled by videodev.c */int (*vidioc_g_std) (struct file *file, void *fh, v4l2_std_id *norm);int (*vidioc_s_std) (struct file *file, void *fh, v4l2_std_id *norm);int (*vidioc_querystd) (struct file *file, void *fh, v4l2_std_id *a);/* Input handling */int (*vidioc_enum_input)(struct file *file, void *fh, struct v4l2_input *inp);int (*vidioc_g_input) (struct file *file, void *fh, unsigned int *i);int (*vidioc_s_input) (struct file *file, void *fh, unsigned int i);/* Output handling */int (*vidioc_enum_output) (struct file *file, void *fh, struct v4l2_output *a);int (*vidioc_g_output) (struct file *file, void *fh, unsigned int *i);int (*vidioc_s_output) (struct file *file, void *fh, unsigned int i);/* Control handling */int (*vidioc_queryctrl) (struct file *file, void *fh,struct v4l2_queryctrl *a);int (*vidioc_g_ctrl) (struct file *file, void *fh,struct v4l2_control *a);int (*vidioc_noti_ctrl) (struct file *file, void *fh,struct v4l2_noti_control *a);int (*vidioc_s_ctrl) (struct file *file, void *fh,struct v4l2_control *a);int (*vidioc_g_ext_ctrls) (struct file *file, void *fh,struct v4l2_ext_controls *a);int (*vidioc_s_ext_ctrls) (struct file *file, void *fh,struct v4l2_ext_controls *a);int (*vidioc_try_ext_ctrls) (struct file *file, void *fh,struct v4l2_ext_controls *a);int (*vidioc_querymenu) (struct file *file, void *fh,struct v4l2_querymenu *a);/* Audio ioctls */int (*vidioc_enumaudio) (struct file *file, void *fh,struct v4l2_audio *a);int (*vidioc_g_audio) (struct file *file, void *fh,struct v4l2_audio *a);int (*vidioc_s_audio) (struct file *file, void *fh,struct v4l2_audio *a);/* Audio out ioctls */int (*vidioc_enumaudout) (struct file *file, void *fh,struct v4l2_audioout *a);int (*vidioc_g_audout) (struct file *file, void *fh,struct v4l2_audioout *a);int (*vidioc_s_audout) (struct file *file, void *fh,struct v4l2_audioout *a);int (*vidioc_g_modulator) (struct file *file, void *fh,struct v4l2_modulator *a);int (*vidioc_s_modulator) (struct file *file, void *fh,struct v4l2_modulator *a);/* Crop ioctls */int (*vidioc_cropcap) (struct file *file, void *fh,struct v4l2_cropcap *a);int (*vidioc_g_crop) (struct file *file, void *fh,struct v4l2_crop *a);int (*vidioc_s_crop) (struct file *file, void *fh,struct v4l2_crop *a);/* Compression ioctls */int (*vidioc_g_jpegcomp) (struct file *file, void *fh,struct v4l2_jpegcompression *a);int (*vidioc_s_jpegcomp) (struct file *file, void *fh,struct v4l2_jpegcompression *a);int (*vidioc_g_enc_index) (struct file *file, void *fh,struct v4l2_enc_idx *a);int (*vidioc_encoder_cmd) (struct file *file, void *fh,struct v4l2_encoder_cmd *a);int (*vidioc_try_encoder_cmd) (struct file *file, void *fh,struct v4l2_encoder_cmd *a);/* Stream type-dependent parameter ioctls */int (*vidioc_g_parm) (struct file *file, void *fh,struct v4l2_streamparm *a);int (*vidioc_s_parm) (struct file *file, void *fh,struct v4l2_streamparm *a);/* Tuner ioctls */int (*vidioc_g_tuner) (struct file *file, void *fh,struct v4l2_tuner *a);int (*vidioc_s_tuner) (struct file *file, void *fh,struct v4l2_tuner *a);int (*vidioc_g_frequency) (struct file *file, void *fh,struct v4l2_frequency *a);int (*vidioc_s_frequency) (struct file *file, void *fh,struct v4l2_frequency *a);/* Sliced VBI cap */int (*vidioc_g_sliced_vbi_cap) (struct file *file, void *fh,struct v4l2_sliced_vbi_cap *a);/* Log status ioctl */int (*vidioc_log_status) (struct file *file, void *fh);int (*vidioc_s_hw_freq_seek) (struct file *file, void *fh,struct v4l2_hw_freq_seek *a);/* Debugging ioctls */#ifdef CONFIG_VIDEO_ADV_DEBUGint (*vidioc_g_register) (struct file *file, void *fh,struct v4l2_dbg_register *reg);int (*vidioc_s_register) (struct file *file, void *fh,struct v4l2_dbg_register *reg);#endifint (*vidioc_g_chip_ident) (struct file *file, void *fh,struct v4l2_dbg_chip_ident *chip);int (*vidioc_enum_framesizes) (struct file *file, void *fh, struct v4l2_frmsizeenum *fsize);int (*vidioc_enum_frameintervals) (struct file *file, void *fh, struct v4l2_frmivalenum *fival);/* DV Timings IOCTLs */int (*vidioc_enum_dv_presets) (struct file *file, void *fh, struct v4l2_dv_enum_preset *preset);int (*vidioc_s_dv_preset) (struct file *file, void *fh, struct v4l2_dv_preset *preset);int (*vidioc_g_dv_preset) (struct file *file, void *fh, struct v4l2_dv_preset *preset);int (*vidioc_query_dv_preset) (struct file *file, void *fh,struct v4l2_dv_preset *qpreset);int (*vidioc_s_dv_timings) (struct file *file, void *fh, struct v4l2_dv_timings *timings);int (*vidioc_g_dv_timings) (struct file *file, void *fh, struct v4l2_dv_timings *timings);int (*vidioc_subscribe_event) (struct v4l2_fh *fh,struct v4l2_event_subscription *sub);int (*vidioc_unsubscribe_event)(struct v4l2_fh *fh,struct v4l2_event_subscription *sub);/* For other private ioctls */long (*vidioc_default) (struct file *file, void *fh,bool valid_prio, int cmd, void *arg);};常用IOCTL函数介绍:
.vidioc_querycap = vidioc_querycap, //查询驱动功能
.vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap, //获取当前驱动支持的视频格式
.vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap, //读取当前驱动的频捕获格式
.vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap, //设置当前驱动的频捕获格式
.vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap, //验证当前驱动的显示格式
.vidioc_reqbufs = vidioc_reqbufs, //分配内存
.vidioc_querybuf = vidioc_querybuf, //把VIDIOC_REQBUFS中分配的数据缓存转换成物理地址
.vidioc_qbuf = vidioc_qbuf, //把数据从缓存中读取出来
.vidioc_dqbuf = vidioc_dqbuf, //把数据放回缓存队列
.vidioc_streamon = vidioc_streamon, //开始视频显示函数
.vidioc_streamoff = vidioc_streamoff, //结束视频显示函数
.vidioc_cropcap = vidioc_cropcap, //查询驱动的修剪能力
.vidioc_g_crop = vidioc_g_crop, //读取视频信号的矩形边框
.vidioc_s_crop = vidioc_s_crop, //设置视频信号的矩形边框
.vidioc_querystd = vidioc_querystd, //检查当前视频设备支持的标准,例如PAL或NTSC。
涉及到的函数:
const char *v4l2_norm_to_name(v4l2_std_id id);//把id转化成人们熟知的各种制式,例如pal
void v4l2_video_std_frame_period(int id, struct v4l2_fract *frameperiod);//设置一帧时间为给定的标准
int v4l2_video_std_construct(struct v4l2_standard *vs,int id, const char *name);//按照id和名字填充v4l2_standard结构体,会调用到v4l2_video_std_frame_period
void v4l_printk_ioctl(unsigned int cmd);//用来调试debug
long video_usercopy(struct file *file, unsigned int cmd,unsigned long arg, v4l2_kioctl func);
long video_ioctl2(struct file *file,unsigned int cmd, unsigned long arg);//调用video_usercopy
很明显比较重要的是video_usercopy函数,下面来分析一下:
longvideo_usercopy(struct file *file, unsigned int cmd, unsigned long arg, v4l2_kioctl func){charsbuf[128];void *mbuf = NULL;void*parg = (void *)arg;longerr = -EINVAL;boolhas_array_args;size_t array_size = 0;void __user *user_ptr = NULL;void**kernel_ptr = NULL;/* Copy arguments into temp kernel buffer */if (_IOC_DIR(cmd) != _IOC_NONE) {if (_IOC_SIZE(cmd) <= sizeof(sbuf)) {parg = sbuf;} else {/* too big to allocate from stack */mbuf = kmalloc(_IOC_SIZE(cmd), GFP_KERNEL);if (NULL == mbuf)return -ENOMEM;parg = mbuf;}err = -EFAULT;if (_IOC_DIR(cmd) & _IOC_WRITE) {unsigned long n = cmd_input_size(cmd);if (copy_from_user(parg, (void __user *)arg, n))goto out;/* zero out anything we don't copy from userspace */if (n < _IOC_SIZE(cmd))memset((u8 *)parg + n, 0, _IOC_SIZE(cmd) - n);} else {/* read-only ioctl */memset(parg, 0, _IOC_SIZE(cmd));}}err = check_array_args(cmd, parg, &array_size, &user_ptr, &kernel_ptr);if (err < 0)goto out;has_array_args = err;if (has_array_args) {/* * When adding new types of array args, make sure that the * parent argument to ioctl (which contains the pointer to the * array) fits into sbuf (so that mbuf will still remain * unused up to here). */mbuf = kmalloc(array_size, GFP_KERNEL);err = -ENOMEM;if (NULL == mbuf)goto out_array_args;err = -EFAULT;if (copy_from_user(mbuf, user_ptr, array_size))goto out_array_args;*kernel_ptr = mbuf;}/* Handles IOCTL */err = func(file, cmd, parg);if (err == -ENOIOCTLCMD)err = -EINVAL;if (has_array_args) {*kernel_ptr = user_ptr;if (copy_to_user(user_ptr, mbuf, array_size))err = -EFAULT;goto out_array_args;}if (err < 0)goto out;out_array_args:/* Copy results into user buffer */switch (_IOC_DIR(cmd)) {case _IOC_READ:case (_IOC_WRITE | _IOC_READ):if (copy_to_user((void __user *)arg, parg, _IOC_SIZE(cmd)))err = -EFAULT;break;}out:kfree(mbuf);return err;}可以看到video_usercopy根据arg变量传送的内存大小不同,parg指向内存大小不同(生成结构体不同),并使用传入的func来处理cmd命令。由video_usercopy(file, cmd, arg, __video_do_ioctl)知,func是 __video_do_ioctl,分析这个函数。
static long __video_do_ioctl(struct file *file,unsigned int cmd, void *arg){struct video_device *vfd = video_devdata(file);const struct v4l2_ioctl_ops *ops = vfd->ioctl_ops;void *fh = file->private_data;struct v4l2_fh *vfh = NULL;struct v4l2_format f_copy;int use_fh_prio = 0;long ret = -EINVAL;if (ops == NULL) {printk(KERN_WARNING "videodev: \"%s\" has no ioctl_ops.\n",vfd->name);return -EINVAL;}if ((vfd->debug & V4L2_DEBUG_IOCTL) &&!(vfd->debug & V4L2_DEBUG_IOCTL_ARG)) {v4l_print_ioctl(vfd->name, cmd);printk(KERN_CONT "\n");}if (test_bit(V4L2_FL_USES_V4L2_FH, &vfd->flags)) {vfh = file->private_data;use_fh_prio = test_bit(V4L2_FL_USE_FH_PRIO, &vfd->flags);}if (use_fh_prio) {switch (cmd) {case VIDIOC_S_CTRL:case VIDIOC_S_STD:case VIDIOC_S_INPUT:case VIDIOC_S_OUTPUT:case VIDIOC_S_TUNER:case VIDIOC_S_FREQUENCY:case VIDIOC_S_FMT:case VIDIOC_S_CROP:case VIDIOC_S_AUDIO:case VIDIOC_S_AUDOUT:case VIDIOC_S_EXT_CTRLS:case VIDIOC_S_FBUF:case VIDIOC_S_PRIORITY:case VIDIOC_S_DV_PRESET:case VIDIOC_S_DV_TIMINGS:case VIDIOC_S_JPEGCOMP:case VIDIOC_S_MODULATOR:case VIDIOC_S_PARM:case VIDIOC_S_HW_FREQ_SEEK:case VIDIOC_ENCODER_CMD:case VIDIOC_OVERLAY:case VIDIOC_REQBUFS:case VIDIOC_STREAMON:case VIDIOC_STREAMOFF:ret = v4l2_prio_check(vfd->prio, vfh->prio);if (ret)goto exit_prio;ret = -EINVAL;break;}}switch (cmd) {/* --- capabilities ------------------------------------------ */case VIDIOC_QUERYCAP:{struct v4l2_capability *cap = (struct v4l2_capability *)arg;if (!ops->vidioc_querycap)break;ret = ops->vidioc_querycap(file, fh, cap);if (!ret)dbgarg(cmd, "driver=%s, card=%s, bus=%s, ""version=0x%08x, ""capabilities=0x%08x\n",cap->driver, cap->card, cap->bus_info,cap->version,cap->capabilities);break;}/* --- priority ------------------------------------------ */case VIDIOC_G_PRIORITY:{enum v4l2_priority *p = arg;if (ops->vidioc_g_priority) {ret = ops->vidioc_g_priority(file, fh, p);} else if (use_fh_prio) {*p = v4l2_prio_max(&vfd->v4l2_dev->prio);ret = 0;}if (!ret)dbgarg(cmd, "priority is %d\n", *p);break;}case VIDIOC_S_PRIORITY:{enum v4l2_priority *p = arg;if (!ops->vidioc_s_priority && !use_fh_prio)break;dbgarg(cmd, "setting priority to %d\n", *p);if (ops->vidioc_s_priority)ret = ops->vidioc_s_priority(file, fh, *p);elseret = v4l2_prio_change(&vfd->v4l2_dev->prio, &vfh->prio, *p);break;}/* --- capture ioctls ---------------------------------------- */case VIDIOC_ENUM_FMT:{struct v4l2_fmtdesc *f = arg;switch (f->type) {case V4L2_BUF_TYPE_VIDEO_CAPTURE:if (ops->vidioc_enum_fmt_vid_cap)ret = ops->vidioc_enum_fmt_vid_cap(file, fh, f);break;case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:if (ops->vidioc_enum_fmt_vid_cap_mplane)ret = ops->vidioc_enum_fmt_vid_cap_mplane(file,fh, f);break;case V4L2_BUF_TYPE_VIDEO_OVERLAY:if (ops->vidioc_enum_fmt_vid_overlay)ret = ops->vidioc_enum_fmt_vid_overlay(file,fh, f);break;case V4L2_BUF_TYPE_VIDEO_OUTPUT:if (ops->vidioc_enum_fmt_vid_out)ret = ops->vidioc_enum_fmt_vid_out(file, fh, f);break;case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:if (ops->vidioc_enum_fmt_vid_out_mplane)ret = ops->vidioc_enum_fmt_vid_out_mplane(file,fh, f);break;case V4L2_BUF_TYPE_PRIVATE:if (ops->vidioc_enum_fmt_type_private)ret = ops->vidioc_enum_fmt_type_private(file,fh, f);break;default:break;}if (!ret)dbgarg(cmd, "index=%d, type=%d, flags=%d, ""pixelformat=%c%c%c%c, description='%s'\n",f->index, f->type, f->flags,(f->pixelformat & 0xff),(f->pixelformat >> 8) & 0xff,(f->pixelformat >> 16) & 0xff,(f->pixelformat >> 24) & 0xff,f->description);break;}case VIDIOC_G_FMT:{struct v4l2_format *f = (struct v4l2_format *)arg;/* FIXME: Should be one dump per type */dbgarg(cmd, "type=%s\n", prt_names(f->type, v4l2_type_names));switch (f->type) {case V4L2_BUF_TYPE_VIDEO_CAPTURE:if (ops->vidioc_g_fmt_vid_cap) {ret = ops->vidioc_g_fmt_vid_cap(file, fh, f);} else if (ops->vidioc_g_fmt_vid_cap_mplane) {if (fmt_sp_to_mp(f, &f_copy))break;ret = ops->vidioc_g_fmt_vid_cap_mplane(file, fh, &f_copy);if (ret)break;/* Driver is currently in multi-planar format, * we can't return it in single-planar API*/if (f_copy.fmt.pix_mp.num_planes > 1) {ret = -EBUSY;break;}ret = fmt_mp_to_sp(&f_copy, f);}if (!ret)v4l_print_pix_fmt(vfd, &f->fmt.pix);break;case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:if (ops->vidioc_g_fmt_vid_cap_mplane) {ret = ops->vidioc_g_fmt_vid_cap_mplane(file,fh, f);} else if (ops->vidioc_g_fmt_vid_cap) {if (fmt_mp_to_sp(f, &f_copy))break;ret = ops->vidioc_g_fmt_vid_cap(file,fh, &f_copy);if (ret)break;ret = fmt_sp_to_mp(&f_copy, f);}if (!ret)v4l_print_pix_fmt_mplane(vfd, &f->fmt.pix_mp);break;case V4L2_BUF_TYPE_VIDEO_OVERLAY:if (ops->vidioc_g_fmt_vid_overlay)ret = ops->vidioc_g_fmt_vid_overlay(file, fh, f);break;case V4L2_BUF_TYPE_VIDEO_OUTPUT:if (ops->vidioc_g_fmt_vid_out) {ret = ops->vidioc_g_fmt_vid_out(file, fh, f);} else if (ops->vidioc_g_fmt_vid_out_mplane) {if (fmt_sp_to_mp(f, &f_copy))break;ret = ops->vidioc_g_fmt_vid_out_mplane(file, fh,&f_copy);if (ret)break;/* Driver is currently in multi-planar format, * we can't return it in single-planar API*/if (f_copy.fmt.pix_mp.num_planes > 1) {ret = -EBUSY;break;}ret = fmt_mp_to_sp(&f_copy, f);}if (!ret)v4l_print_pix_fmt(vfd, &f->fmt.pix);break;case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:if (ops->vidioc_g_fmt_vid_out_mplane) {ret = ops->vidioc_g_fmt_vid_out_mplane(file,fh, f);} else if (ops->vidioc_g_fmt_vid_out) {if (fmt_mp_to_sp(f, &f_copy))break;ret = ops->vidioc_g_fmt_vid_out(file,fh, &f_copy);if (ret)break;ret = fmt_sp_to_mp(&f_copy, f);}if (!ret)v4l_print_pix_fmt_mplane(vfd, &f->fmt.pix_mp);break;case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY:if (ops->vidioc_g_fmt_vid_out_overlay)ret = ops->vidioc_g_fmt_vid_out_overlay(file, fh, f);break;case V4L2_BUF_TYPE_VBI_CAPTURE:if (ops->vidioc_g_fmt_vbi_cap)ret = ops->vidioc_g_fmt_vbi_cap(file, fh, f);break;case V4L2_BUF_TYPE_VBI_OUTPUT:if (ops->vidioc_g_fmt_vbi_out)ret = ops->vidioc_g_fmt_vbi_out(file, fh, f);break;case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE:if (ops->vidioc_g_fmt_sliced_vbi_cap)ret = ops->vidioc_g_fmt_sliced_vbi_cap(file,fh, f);break;case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT:if (ops->vidioc_g_fmt_sliced_vbi_out)ret = ops->vidioc_g_fmt_sliced_vbi_out(file,fh, f);break;case V4L2_BUF_TYPE_PRIVATE:if (ops->vidioc_g_fmt_type_private)ret = ops->vidioc_g_fmt_type_private(file,fh, f);break;}break;}case VIDIOC_S_FMT:{struct v4l2_format *f = (struct v4l2_format *)arg;/* FIXME: Should be one dump per type */dbgarg(cmd, "type=%s\n", prt_names(f->type, v4l2_type_names));switch (f->type) {case V4L2_BUF_TYPE_VIDEO_CAPTURE:CLEAR_AFTER_FIELD(f, fmt.pix);v4l_print_pix_fmt(vfd, &f->fmt.pix);if (ops->vidioc_s_fmt_vid_cap) {ret = ops->vidioc_s_fmt_vid_cap(file, fh, f);} else if (ops->vidioc_s_fmt_vid_cap_mplane) {if (fmt_sp_to_mp(f, &f_copy))break;ret = ops->vidioc_s_fmt_vid_cap_mplane(file, fh,&f_copy);if (ret)break;if (f_copy.fmt.pix_mp.num_planes > 1) {/* Drivers shouldn't adjust from 1-plane * to more than 1-plane formats */ret = -EBUSY;WARN_ON(1);break;}ret = fmt_mp_to_sp(&f_copy, f);}break;case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:CLEAR_AFTER_FIELD(f, fmt.pix_mp);v4l_print_pix_fmt_mplane(vfd, &f->fmt.pix_mp);if (ops->vidioc_s_fmt_vid_cap_mplane) {ret = ops->vidioc_s_fmt_vid_cap_mplane(file,fh, f);} else if (ops->vidioc_s_fmt_vid_cap &&f->fmt.pix_mp.num_planes == 1) {if (fmt_mp_to_sp(f, &f_copy))break;ret = ops->vidioc_s_fmt_vid_cap(file,fh, &f_copy);if (ret)break;ret = fmt_sp_to_mp(&f_copy, f);}break;case V4L2_BUF_TYPE_VIDEO_OVERLAY:CLEAR_AFTER_FIELD(f, fmt.win);if (ops->vidioc_s_fmt_vid_overlay)ret = ops->vidioc_s_fmt_vid_overlay(file, fh, f);break;case V4L2_BUF_TYPE_VIDEO_OUTPUT:CLEAR_AFTER_FIELD(f, fmt.pix);v4l_print_pix_fmt(vfd, &f->fmt.pix);if (ops->vidioc_s_fmt_vid_out) {ret = ops->vidioc_s_fmt_vid_out(file, fh, f);} else if (ops->vidioc_s_fmt_vid_out_mplane) {if (fmt_sp_to_mp(f, &f_copy))break;ret = ops->vidioc_s_fmt_vid_out_mplane(file, fh,&f_copy);if (ret)break;if (f_copy.fmt.pix_mp.num_planes > 1) {/* Drivers shouldn't adjust from 1-plane * to more than 1-plane formats */ret = -EBUSY;WARN_ON(1);break;}ret = fmt_mp_to_sp(&f_copy, f);}break;case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:CLEAR_AFTER_FIELD(f, fmt.pix_mp);v4l_print_pix_fmt_mplane(vfd, &f->fmt.pix_mp);if (ops->vidioc_s_fmt_vid_out_mplane) {ret = ops->vidioc_s_fmt_vid_out_mplane(file,fh, f);} else if (ops->vidioc_s_fmt_vid_out &&f->fmt.pix_mp.num_planes == 1) {if (fmt_mp_to_sp(f, &f_copy))break;ret = ops->vidioc_s_fmt_vid_out(file,fh, &f_copy);if (ret)break;ret = fmt_mp_to_sp(&f_copy, f);}break;case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY:CLEAR_AFTER_FIELD(f, fmt.win);if (ops->vidioc_s_fmt_vid_out_overlay)ret = ops->vidioc_s_fmt_vid_out_overlay(file,fh, f);break;case V4L2_BUF_TYPE_VBI_CAPTURE:CLEAR_AFTER_FIELD(f, fmt.vbi);if (ops->vidioc_s_fmt_vbi_cap)ret = ops->vidioc_s_fmt_vbi_cap(file, fh, f);break;case V4L2_BUF_TYPE_VBI_OUTPUT:CLEAR_AFTER_FIELD(f, fmt.vbi);if (ops->vidioc_s_fmt_vbi_out)ret = ops->vidioc_s_fmt_vbi_out(file, fh, f);break;case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE:CLEAR_AFTER_FIELD(f, fmt.sliced);if (ops->vidioc_s_fmt_sliced_vbi_cap)ret = ops->vidioc_s_fmt_sliced_vbi_cap(file,fh, f);break;case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT:CLEAR_AFTER_FIELD(f, fmt.sliced);if (ops->vidioc_s_fmt_sliced_vbi_out)ret = ops->vidioc_s_fmt_sliced_vbi_out(file,fh, f);break;case V4L2_BUF_TYPE_PRIVATE:/* CLEAR_AFTER_FIELD(f, fmt.raw_data); <- does nothing */if (ops->vidioc_s_fmt_type_private)ret = ops->vidioc_s_fmt_type_private(file,fh, f);break;}break;}case VIDIOC_TRY_FMT:{struct v4l2_format *f = (struct v4l2_format *)arg;/* FIXME: Should be one dump per type */dbgarg(cmd, "type=%s\n", prt_names(f->type,v4l2_type_names));switch (f->type) {case V4L2_BUF_TYPE_VIDEO_CAPTURE:CLEAR_AFTER_FIELD(f, fmt.pix);if (ops->vidioc_try_fmt_vid_cap) {ret = ops->vidioc_try_fmt_vid_cap(file, fh, f);} else if (ops->vidioc_try_fmt_vid_cap_mplane) {if (fmt_sp_to_mp(f, &f_copy))break;ret = ops->vidioc_try_fmt_vid_cap_mplane(file,fh, &f_copy);if (ret)break;if (f_copy.fmt.pix_mp.num_planes > 1) {/* Drivers shouldn't adjust from 1-plane * to more than 1-plane formats */ret = -EBUSY;WARN_ON(1);break;}ret = fmt_mp_to_sp(&f_copy, f);}if (!ret)v4l_print_pix_fmt(vfd, &f->fmt.pix);break;case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:CLEAR_AFTER_FIELD(f, fmt.pix_mp);if (ops->vidioc_try_fmt_vid_cap_mplane) {ret = ops->vidioc_try_fmt_vid_cap_mplane(file, fh, f);} else if (ops->vidioc_try_fmt_vid_cap &&f->fmt.pix_mp.num_planes == 1) {if (fmt_mp_to_sp(f, &f_copy))break;ret = ops->vidioc_try_fmt_vid_cap(file, fh, &f_copy);if (ret)break;ret = fmt_sp_to_mp(&f_copy, f);}if (!ret)v4l_print_pix_fmt_mplane(vfd, &f->fmt.pix_mp);break;case V4L2_BUF_TYPE_VIDEO_OVERLAY:CLEAR_AFTER_FIELD(f, fmt.win);if (ops->vidioc_try_fmt_vid_overlay)ret = ops->vidioc_try_fmt_vid_overlay(file,fh, f);break;case V4L2_BUF_TYPE_VIDEO_OUTPUT:CLEAR_AFTER_FIELD(f, fmt.pix);if (ops->vidioc_try_fmt_vid_out) {ret = ops->vidioc_try_fmt_vid_out(file, fh, f);} else if (ops->vidioc_try_fmt_vid_out_mplane) {if (fmt_sp_to_mp(f, &f_copy))break;ret = ops->vidioc_try_fmt_vid_out_mplane(file,fh, &f_copy);if (ret)break;if (f_copy.fmt.pix_mp.num_planes > 1) {/* Drivers shouldn't adjust from 1-plane * to more than 1-plane formats */ret = -EBUSY;WARN_ON(1);break;}ret = fmt_mp_to_sp(&f_copy, f);}if (!ret)v4l_print_pix_fmt(vfd, &f->fmt.pix);break;case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:CLEAR_AFTER_FIELD(f, fmt.pix_mp);if (ops->vidioc_try_fmt_vid_out_mplane) {ret = ops->vidioc_try_fmt_vid_out_mplane(file, fh, f);} else if (ops->vidioc_try_fmt_vid_out &&f->fmt.pix_mp.num_planes == 1) {if (fmt_mp_to_sp(f, &f_copy))break;ret = ops->vidioc_try_fmt_vid_out(file, fh, &f_copy);if (ret)break;ret = fmt_sp_to_mp(&f_copy, f);}if (!ret)v4l_print_pix_fmt_mplane(vfd, &f->fmt.pix_mp);break;case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY:CLEAR_AFTER_FIELD(f, fmt.win);if (ops->vidioc_try_fmt_vid_out_overlay)ret = ops->vidioc_try_fmt_vid_out_overlay(file, fh, f);break;case V4L2_BUF_TYPE_VBI_CAPTURE:CLEAR_AFTER_FIELD(f, fmt.vbi);if (ops->vidioc_try_fmt_vbi_cap)ret = ops->vidioc_try_fmt_vbi_cap(file, fh, f);break;case V4L2_BUF_TYPE_VBI_OUTPUT:CLEAR_AFTER_FIELD(f, fmt.vbi);if (ops->vidioc_try_fmt_vbi_out)ret = ops->vidioc_try_fmt_vbi_out(file, fh, f);break;case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE:CLEAR_AFTER_FIELD(f, fmt.sliced);if (ops->vidioc_try_fmt_sliced_vbi_cap)ret = ops->vidioc_try_fmt_sliced_vbi_cap(file,fh, f);break;case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT:CLEAR_AFTER_FIELD(f, fmt.sliced);if (ops->vidioc_try_fmt_sliced_vbi_out)ret = ops->vidioc_try_fmt_sliced_vbi_out(file,fh, f);break;case V4L2_BUF_TYPE_PRIVATE:/* CLEAR_AFTER_FIELD(f, fmt.raw_data); <- does nothing */if (ops->vidioc_try_fmt_type_private)ret = ops->vidioc_try_fmt_type_private(file,fh, f);break;}break;}/* FIXME: Those buf reqs could be handled here, with some changes on videobuf to allow its header to be included at videodev2.h or being merged at videodev2. */case VIDIOC_REQBUFS:{struct v4l2_requestbuffers *p = arg;if (!ops->vidioc_reqbufs)break;ret = check_fmt(ops, p->type);if (ret)break;if (p->type < V4L2_BUF_TYPE_PRIVATE)CLEAR_AFTER_FIELD(p, memory);ret = ops->vidioc_reqbufs(file, fh, p);dbgarg(cmd, "count=%d, type=%s, memory=%s\n",p->count,prt_names(p->type, v4l2_type_names),prt_names(p->memory, v4l2_memory_names));break;}case VIDIOC_QUERYBUF:{struct v4l2_buffer *p = arg;if (!ops->vidioc_querybuf)break;ret = check_fmt(ops, p->type);if (ret)break;ret = ops->vidioc_querybuf(file, fh, p);if (!ret)dbgbuf(cmd, vfd, p);break;}case VIDIOC_QBUF:{struct v4l2_buffer *p = arg;if (!ops->vidioc_qbuf)break;ret = check_fmt(ops, p->type);if (ret)break;ret = ops->vidioc_qbuf(file, fh, p);if (!ret)dbgbuf(cmd, vfd, p);break;}case VIDIOC_DQBUF:{struct v4l2_buffer *p = arg;if (!ops->vidioc_dqbuf)break;ret = check_fmt(ops, p->type);if (ret)break;ret = ops->vidioc_dqbuf(file, fh, p);if (!ret)dbgbuf(cmd, vfd, p);break;}case VIDIOC_OVERLAY:{int *i = arg;if (!ops->vidioc_overlay)break;dbgarg(cmd, "value=%d\n", *i);ret = ops->vidioc_overlay(file, fh, *i);break;}case VIDIOC_G_FBUF:{struct v4l2_framebuffer *p = arg;if (!ops->vidioc_g_fbuf)break;ret = ops->vidioc_g_fbuf(file, fh, arg);if (!ret) {dbgarg(cmd, "capability=0x%x, flags=%d, base=0x%08lx\n",p->capability, p->flags,(unsigned long)p->base);v4l_print_pix_fmt(vfd, &p->fmt);}break;}case VIDIOC_S_FBUF:{struct v4l2_framebuffer *p = arg;if (!ops->vidioc_s_fbuf)break;dbgarg(cmd, "capability=0x%x, flags=%d, base=0x%08lx\n",p->capability, p->flags, (unsigned long)p->base);v4l_print_pix_fmt(vfd, &p->fmt);ret = ops->vidioc_s_fbuf(file, fh, arg);break;}case VIDIOC_STREAMON:{enum v4l2_buf_type i = *(int *)arg;if (!ops->vidioc_streamon)break;dbgarg(cmd, "type=%s\n", prt_names(i, v4l2_type_names));ret = ops->vidioc_streamon(file, fh, i);break;}case VIDIOC_STREAMOFF:{enum v4l2_buf_type i = *(int *)arg;if (!ops->vidioc_streamoff)break;dbgarg(cmd, "type=%s\n", prt_names(i, v4l2_type_names));ret = ops->vidioc_streamoff(file, fh, i);break;}/* ---------- tv norms ---------- */case VIDIOC_ENUMSTD:{struct v4l2_standard *p = arg;v4l2_std_id id = vfd->tvnorms, curr_id = 0;unsigned int index = p->index, i, j = 0;const char *descr = "";/* Return norm array in a canonical way */for (i = 0; i <= index && id; i++) {/* last std value in the standards array is 0, so this while always ends there since (id & 0) == 0. */while ((id & standards[j].std) != standards[j].std)j++;curr_id = standards[j].std;descr = standards[j].descr;j++;if (curr_id == 0)break;if (curr_id != V4L2_STD_PAL && curr_id != V4L2_STD_SECAM && curr_id != V4L2_STD_NTSC)id &= ~curr_id;}if (i <= index)break;v4l2_video_std_construct(p, curr_id, descr);dbgarg(cmd, "index=%d, id=0x%Lx, name=%s, fps=%d/%d, ""framelines=%d\n", p->index,(unsigned long long)p->id, p->name,p->frameperiod.numerator,p->frameperiod.denominator,p->framelines);ret = 0;break;}case VIDIOC_G_STD:{v4l2_std_id *id = arg;ret = 0;/* Calls the specific handler */if (ops->vidioc_g_std)ret = ops->vidioc_g_std(file, fh, id);else if (vfd->current_norm)*id = vfd->current_norm;elseret = -EINVAL;if (!ret)dbgarg(cmd, "std=0x%08Lx\n", (long long unsigned)*id);break;}case VIDIOC_S_STD:{v4l2_std_id *id = arg, norm;dbgarg(cmd, "std=%08Lx\n", (long long unsigned)*id);norm = (*id) & vfd->tvnorms;if (vfd->tvnorms && !norm)/* Check if std is supported */break;/* Calls the specific handler */if (ops->vidioc_s_std)ret = ops->vidioc_s_std(file, fh, &norm);elseret = -EINVAL;/* Updates standard information */if (ret >= 0)vfd->current_norm = norm;break;}case VIDIOC_QUERYSTD:{v4l2_std_id *p = arg;if (!ops->vidioc_querystd)break;ret = ops->vidioc_querystd(file, fh, arg);if (!ret)dbgarg(cmd, "detected std=%08Lx\n",(unsigned long long)*p);break;}/* ------ input switching ---------- *//* FIXME: Inputs can be handled inside videodev2 */case VIDIOC_ENUMINPUT:{struct v4l2_input *p = arg;/* * We set the flags for CAP_PRESETS, CAP_CUSTOM_TIMINGS & * CAP_STD here based on ioctl handler provided by the * driver. If the driver doesn't support these * for a specific input, it must override these flags. */if (ops->vidioc_s_std)p->capabilities |= V4L2_IN_CAP_STD;if (ops->vidioc_s_dv_preset)p->capabilities |= V4L2_IN_CAP_PRESETS;if (ops->vidioc_s_dv_timings)p->capabilities |= V4L2_IN_CAP_CUSTOM_TIMINGS;if (!ops->vidioc_enum_input)break;ret = ops->vidioc_enum_input(file, fh, p);if (!ret)dbgarg(cmd, "index=%d, name=%s, type=%d, ""audioset=%d, ""tuner=%d, std=%08Lx, status=%d\n",p->index, p->name, p->type, p->audioset,p->tuner,(unsigned long long)p->std,p->status);break;}case VIDIOC_G_INPUT:{unsigned int *i = arg;if (!ops->vidioc_g_input)break;ret = ops->vidioc_g_input(file, fh, i);if (!ret)dbgarg(cmd, "value=%d\n", *i);break;}case VIDIOC_S_INPUT:{unsigned int *i = arg;if (!ops->vidioc_s_input)break;dbgarg(cmd, "value=%d\n", *i);ret = ops->vidioc_s_input(file, fh, *i);break;}/* ------ output switching ---------- */case VIDIOC_ENUMOUTPUT:{struct v4l2_output *p = arg;if (!ops->vidioc_enum_output)break;/* * We set the flags for CAP_PRESETS, CAP_CUSTOM_TIMINGS & * CAP_STD here based on ioctl handler provided by the * driver. If the driver doesn't support these * for a specific output, it must override these flags. */if (ops->vidioc_s_std)p->capabilities |= V4L2_OUT_CAP_STD;if (ops->vidioc_s_dv_preset)p->capabilities |= V4L2_OUT_CAP_PRESETS;if (ops->vidioc_s_dv_timings)p->capabilities |= V4L2_OUT_CAP_CUSTOM_TIMINGS;ret = ops->vidioc_enum_output(file, fh, p);if (!ret)dbgarg(cmd, "index=%d, name=%s, type=%d, ""audioset=0x%x, ""modulator=%d, std=0x%08Lx\n",p->index, p->name, p->type, p->audioset,p->modulator, (unsigned long long)p->std);break;}case VIDIOC_G_OUTPUT:{unsigned int *i = arg;if (!ops->vidioc_g_output)break;ret = ops->vidioc_g_output(file, fh, i);if (!ret)dbgarg(cmd, "value=%d\n", *i);break;}case VIDIOC_S_OUTPUT:{unsigned int *i = arg;if (!ops->vidioc_s_output)break;dbgarg(cmd, "value=%d\n", *i);ret = ops->vidioc_s_output(file, fh, *i);break;}/* --- controls ---------------------------------------------- */case VIDIOC_QUERYCTRL:{struct v4l2_queryctrl *p = arg;if (vfh && vfh->ctrl_handler)ret = v4l2_queryctrl(vfh->ctrl_handler, p);else if (vfd->ctrl_handler)ret = v4l2_queryctrl(vfd->ctrl_handler, p);else if (ops->vidioc_queryctrl)ret = ops->vidioc_queryctrl(file, fh, p);elsebreak;if (!ret)dbgarg(cmd, "id=0x%x, type=%d, name=%s, min/max=%d/%d, ""step=%d, default=%d, flags=0x%08x\n",p->id, p->type, p->name,p->minimum, p->maximum,p->step, p->default_value, p->flags);elsedbgarg(cmd, "id=0x%x\n", p->id);break;}case VIDIOC_G_CTRL:{struct v4l2_control *p = arg;if (vfh && vfh->ctrl_handler)ret = v4l2_g_ctrl(vfh->ctrl_handler, p);else if (vfd->ctrl_handler)ret = v4l2_g_ctrl(vfd->ctrl_handler, p);else if (ops->vidioc_g_ctrl)ret = ops->vidioc_g_ctrl(file, fh, p);else if (ops->vidioc_g_ext_ctrls) {struct v4l2_ext_controls ctrls;struct v4l2_ext_control ctrl;ctrls.ctrl_class = V4L2_CTRL_ID2CLASS(p->id);ctrls.count = 1;ctrls.controls = &ctrl;ctrl.id = p->id;ctrl.value = p->value;if (check_ext_ctrls(&ctrls, 1)) {ret = ops->vidioc_g_ext_ctrls(file, fh, &ctrls);if (ret == 0)p->value = ctrl.value;}} elsebreak;if (!ret)dbgarg(cmd, "id=0x%x, value=%d\n", p->id, p->value);elsedbgarg(cmd, "id=0x%x\n", p->id);break;}case VIDIOC_NOTI_CTRL:{struct v4l2_noti_control *p = arg;if (vfh && vfh->ctrl_handler)ret = v4l2_noti_ctrl(vfh->ctrl_handler, p);else if (vfd->ctrl_handler)ret = v4l2_noti_ctrl(vfd->ctrl_handler, p);else if (ops->vidioc_noti_ctrl) {ret = ops->vidioc_noti_ctrl(file, fh, p);} elsebreak;if (!ret)dbgarg(cmd, "id=0x%x, value=%d\n", p->id, p->value);elsedbgarg(cmd, "id=0x%x\n", p->id);break;}case VIDIOC_S_CTRL:{struct v4l2_control *p = arg;struct v4l2_ext_controls ctrls;struct v4l2_ext_control ctrl;if (!(vfh && vfh->ctrl_handler) && !vfd->ctrl_handler &&!ops->vidioc_s_ctrl && !ops->vidioc_s_ext_ctrls)break;dbgarg(cmd, "id=0x%x, value=%d\n", p->id, p->value);if (vfh && vfh->ctrl_handler) {ret = v4l2_s_ctrl(vfh->ctrl_handler, p);break;}if (vfd->ctrl_handler) {ret = v4l2_s_ctrl(vfd->ctrl_handler, p);break;}if (ops->vidioc_s_ctrl) {ret = ops->vidioc_s_ctrl(file, fh, p);break;}if (!ops->vidioc_s_ext_ctrls)break;ctrls.ctrl_class = V4L2_CTRL_ID2CLASS(p->id);ctrls.count = 1;ctrls.controls = &ctrl;ctrl.id = p->id;ctrl.value = p->value;if (check_ext_ctrls(&ctrls, 1))ret = ops->vidioc_s_ext_ctrls(file, fh, &ctrls);break;}case VIDIOC_G_EXT_CTRLS:{struct v4l2_ext_controls *p = arg;p->error_idx = p->count;if (vfh && vfh->ctrl_handler)ret = v4l2_g_ext_ctrls(vfh->ctrl_handler, p);else if (vfd->ctrl_handler)ret = v4l2_g_ext_ctrls(vfd->ctrl_handler, p);else if (ops->vidioc_g_ext_ctrls && check_ext_ctrls(p, 0))ret = ops->vidioc_g_ext_ctrls(file, fh, p);elsebreak;v4l_print_ext_ctrls(cmd, vfd, p, !ret);break;}case VIDIOC_S_EXT_CTRLS:{struct v4l2_ext_controls *p = arg;p->error_idx = p->count;if (!(vfh && vfh->ctrl_handler) && !vfd->ctrl_handler &&!ops->vidioc_s_ext_ctrls)break;v4l_print_ext_ctrls(cmd, vfd, p, 1);if (vfh && vfh->ctrl_handler)ret = v4l2_s_ext_ctrls(vfh->ctrl_handler, p);else if (vfd->ctrl_handler)ret = v4l2_s_ext_ctrls(vfd->ctrl_handler, p);else if (check_ext_ctrls(p, 0))ret = ops->vidioc_s_ext_ctrls(file, fh, p);break;}case VIDIOC_TRY_EXT_CTRLS:{struct v4l2_ext_controls *p = arg;p->error_idx = p->count;if (!(vfh && vfh->ctrl_handler) && !vfd->ctrl_handler &&!ops->vidioc_try_ext_ctrls)break;v4l_print_ext_ctrls(cmd, vfd, p, 1);if (vfh && vfh->ctrl_handler)ret = v4l2_try_ext_ctrls(vfh->ctrl_handler, p);else if (vfd->ctrl_handler)ret = v4l2_try_ext_ctrls(vfd->ctrl_handler, p);else if (check_ext_ctrls(p, 0))ret = ops->vidioc_try_ext_ctrls(file, fh, p);break;}case VIDIOC_QUERYMENU:{struct v4l2_querymenu *p = arg;if (vfh && vfh->ctrl_handler)ret = v4l2_querymenu(vfh->ctrl_handler, p);else if (vfd->ctrl_handler)ret = v4l2_querymenu(vfd->ctrl_handler, p);else if (ops->vidioc_querymenu)ret = ops->vidioc_querymenu(file, fh, p);elsebreak;if (!ret)dbgarg(cmd, "id=0x%x, index=%d, name=%s\n",p->id, p->index, p->name);elsedbgarg(cmd, "id=0x%x, index=%d\n",p->id, p->index);break;}/* --- audio ---------------------------------------------- */case VIDIOC_ENUMAUDIO:{struct v4l2_audio *p = arg;if (!ops->vidioc_enumaudio)break;ret = ops->vidioc_enumaudio(file, fh, p);if (!ret)dbgarg(cmd, "index=%d, name=%s, capability=0x%x, ""mode=0x%x\n", p->index, p->name,p->capability, p->mode);elsedbgarg(cmd, "index=%d\n", p->index);break;}case VIDIOC_G_AUDIO:{struct v4l2_audio *p = arg;if (!ops->vidioc_g_audio)break;ret = ops->vidioc_g_audio(file, fh, p);if (!ret)dbgarg(cmd, "index=%d, name=%s, capability=0x%x, ""mode=0x%x\n", p->index,p->name, p->capability, p->mode);elsedbgarg(cmd, "index=%d\n", p->index);break;}case VIDIOC_S_AUDIO:{struct v4l2_audio *p = arg;if (!ops->vidioc_s_audio)break;dbgarg(cmd, "index=%d, name=%s, capability=0x%x, ""mode=0x%x\n", p->index, p->name,p->capability, p->mode);ret = ops->vidioc_s_audio(file, fh, p);break;}case VIDIOC_ENUMAUDOUT:{struct v4l2_audioout *p = arg;if (!ops->vidioc_enumaudout)break;dbgarg(cmd, "Enum for index=%d\n", p->index);ret = ops->vidioc_enumaudout(file, fh, p);if (!ret)dbgarg2("index=%d, name=%s, capability=%d, ""mode=%d\n", p->index, p->name,p->capability, p->mode);break;}case VIDIOC_G_AUDOUT:{struct v4l2_audioout *p = arg;if (!ops->vidioc_g_audout)break;ret = ops->vidioc_g_audout(file, fh, p);if (!ret)dbgarg2("index=%d, name=%s, capability=%d, ""mode=%d\n", p->index, p->name,p->capability, p->mode);break;}case VIDIOC_S_AUDOUT:{struct v4l2_audioout *p = arg;if (!ops->vidioc_s_audout)break;dbgarg(cmd, "index=%d, name=%s, capability=%d, ""mode=%d\n", p->index, p->name,p->capability, p->mode);ret = ops->vidioc_s_audout(file, fh, p);break;}case VIDIOC_G_MODULATOR:{struct v4l2_modulator *p = arg;if (!ops->vidioc_g_modulator)break;ret = ops->vidioc_g_modulator(file, fh, p);if (!ret)dbgarg(cmd, "index=%d, name=%s, ""capability=%d, rangelow=%d,"" rangehigh=%d, txsubchans=%d\n",p->index, p->name, p->capability,p->rangelow, p->rangehigh,p->txsubchans);break;}case VIDIOC_S_MODULATOR:{struct v4l2_modulator *p = arg;if (!ops->vidioc_s_modulator)break;dbgarg(cmd, "index=%d, name=%s, capability=%d, ""rangelow=%d, rangehigh=%d, txsubchans=%d\n",p->index, p->name, p->capability, p->rangelow,p->rangehigh, p->txsubchans);ret = ops->vidioc_s_modulator(file, fh, p);break;}case VIDIOC_G_CROP:{struct v4l2_crop *p = arg;if (!ops->vidioc_g_crop)break;dbgarg(cmd, "type=%s\n", prt_names(p->type, v4l2_type_names));ret = ops->vidioc_g_crop(file, fh, p);if (!ret)dbgrect(vfd, "", &p->c);break;}case VIDIOC_S_CROP:{struct v4l2_crop *p = arg;if (!ops->vidioc_s_crop)break;dbgarg(cmd, "type=%s\n", prt_names(p->type, v4l2_type_names));dbgrect(vfd, "", &p->c);ret = ops->vidioc_s_crop(file, fh, p);break;}case VIDIOC_CROPCAP:{struct v4l2_cropcap *p = arg;/*FIXME: Should also show v4l2_fract pixelaspect */if (!ops->vidioc_cropcap)break;dbgarg(cmd, "type=%s\n", prt_names(p->type, v4l2_type_names));ret = ops->vidioc_cropcap(file, fh, p);if (!ret) {dbgrect(vfd, "bounds ", &p->bounds);dbgrect(vfd, "defrect ", &p->defrect);}break;}case VIDIOC_G_JPEGCOMP:{struct v4l2_jpegcompression *p = arg;if (!ops->vidioc_g_jpegcomp)break;ret = ops->vidioc_g_jpegcomp(file, fh, p);if (!ret)dbgarg(cmd, "quality=%d, APPn=%d, ""APP_len=%d, COM_len=%d, ""jpeg_markers=%d\n",p->quality, p->APPn, p->APP_len,p->COM_len, p->jpeg_markers);break;}case VIDIOC_S_JPEGCOMP:{struct v4l2_jpegcompression *p = arg;if (!ops->vidioc_g_jpegcomp)break;dbgarg(cmd, "quality=%d, APPn=%d, APP_len=%d, ""COM_len=%d, jpeg_markers=%d\n",p->quality, p->APPn, p->APP_len,p->COM_len, p->jpeg_markers);ret = ops->vidioc_s_jpegcomp(file, fh, p);break;}case VIDIOC_G_ENC_INDEX:{struct v4l2_enc_idx *p = arg;if (!ops->vidioc_g_enc_index)break;ret = ops->vidioc_g_enc_index(file, fh, p);if (!ret)dbgarg(cmd, "entries=%d, entries_cap=%d\n",p->entries, p->entries_cap);break;}case VIDIOC_ENCODER_CMD:{struct v4l2_encoder_cmd *p = arg;if (!ops->vidioc_encoder_cmd)break;ret = ops->vidioc_encoder_cmd(file, fh, p);if (!ret)dbgarg(cmd, "cmd=%d, flags=%x\n", p->cmd, p->flags);break;}case VIDIOC_TRY_ENCODER_CMD:{struct v4l2_encoder_cmd *p = arg;if (!ops->vidioc_try_encoder_cmd)break;ret = ops->vidioc_try_encoder_cmd(file, fh, p);if (!ret)dbgarg(cmd, "cmd=%d, flags=%x\n", p->cmd, p->flags);break;}case VIDIOC_G_PARM:{struct v4l2_streamparm *p = arg;if (ops->vidioc_g_parm) {ret = check_fmt(ops, p->type);if (ret)break;ret = ops->vidioc_g_parm(file, fh, p);} else {v4l2_std_id std = vfd->current_norm;if (p->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)break;ret = 0;if (ops->vidioc_g_std)ret = ops->vidioc_g_std(file, fh, &std);else if (std == 0)ret = -EINVAL;if (ret == 0)v4l2_video_std_frame_period(std, &p->parm.capture.timeperframe);}dbgarg(cmd, "type=%d\n", p->type);break;}case VIDIOC_S_PARM:{struct v4l2_streamparm *p = arg;if (!ops->vidioc_s_parm)break;ret = check_fmt(ops, p->type);if (ret)break;dbgarg(cmd, "type=%d\n", p->type);ret = ops->vidioc_s_parm(file, fh, p);break;}case VIDIOC_G_TUNER:{struct v4l2_tuner *p = arg;if (!ops->vidioc_g_tuner)break;p->type = (vfd->vfl_type == VFL_TYPE_RADIO) ?V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV;ret = ops->vidioc_g_tuner(file, fh, p);if (!ret)dbgarg(cmd, "index=%d, name=%s, type=%d, ""capability=0x%x, rangelow=%d, ""rangehigh=%d, signal=%d, afc=%d, ""rxsubchans=0x%x, audmode=%d\n",p->index, p->name, p->type,p->capability, p->rangelow,p->rangehigh, p->signal, p->afc,p->rxsubchans, p->audmode);break;}case VIDIOC_S_TUNER:{struct v4l2_tuner *p = arg;if (!ops->vidioc_s_tuner)break;p->type = (vfd->vfl_type == VFL_TYPE_RADIO) ?V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV;dbgarg(cmd, "index=%d, name=%s, type=%d, ""capability=0x%x, rangelow=%d, ""rangehigh=%d, signal=%d, afc=%d, ""rxsubchans=0x%x, audmode=%d\n",p->index, p->name, p->type,p->capability, p->rangelow,p->rangehigh, p->signal, p->afc,p->rxsubchans, p->audmode);ret = ops->vidioc_s_tuner(file, fh, p);break;}case VIDIOC_G_FREQUENCY:{struct v4l2_frequency *p = arg;if (!ops->vidioc_g_frequency)break;p->type = (vfd->vfl_type == VFL_TYPE_RADIO) ?V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV;ret = ops->vidioc_g_frequency(file, fh, p);if (!ret)dbgarg(cmd, "tuner=%d, type=%d, frequency=%d\n",p->tuner, p->type, p->frequency);break;}case VIDIOC_S_FREQUENCY:{struct v4l2_frequency *p = arg;if (!ops->vidioc_s_frequency)break;dbgarg(cmd, "tuner=%d, type=%d, frequency=%d\n",p->tuner, p->type, p->frequency);ret = ops->vidioc_s_frequency(file, fh, p);break;}case VIDIOC_G_SLICED_VBI_CAP:{struct v4l2_sliced_vbi_cap *p = arg;if (!ops->vidioc_g_sliced_vbi_cap)break;/* Clear up to type, everything after type is zerod already */memset(p, 0, offsetof(struct v4l2_sliced_vbi_cap, type));dbgarg(cmd, "type=%s\n", prt_names(p->type, v4l2_type_names));ret = ops->vidioc_g_sliced_vbi_cap(file, fh, p);if (!ret)dbgarg2("service_set=%d\n", p->service_set);break;}case VIDIOC_LOG_STATUS:{if (!ops->vidioc_log_status)break;ret = ops->vidioc_log_status(file, fh);break;}#ifdef CONFIG_VIDEO_ADV_DEBUGcase VIDIOC_DBG_G_REGISTER:{struct v4l2_dbg_register *p = arg;if (ops->vidioc_g_register) {if (!capable(CAP_SYS_ADMIN))ret = -EPERM;elseret = ops->vidioc_g_register(file, fh, p);}break;}case VIDIOC_DBG_S_REGISTER:{struct v4l2_dbg_register *p = arg;if (ops->vidioc_s_register) {if (!capable(CAP_SYS_ADMIN))ret = -EPERM;elseret = ops->vidioc_s_register(file, fh, p);}break;}#endifcase VIDIOC_DBG_G_CHIP_IDENT:{struct v4l2_dbg_chip_ident *p = arg;if (!ops->vidioc_g_chip_ident)break;p->ident = V4L2_IDENT_NONE;p->revision = 0;ret = ops->vidioc_g_chip_ident(file, fh, p);if (!ret)dbgarg(cmd, "chip_ident=%u, revision=0x%x\n", p->ident, p->revision);break;}case VIDIOC_S_HW_FREQ_SEEK:{struct v4l2_hw_freq_seek *p = arg;enum v4l2_tuner_type type;if (!ops->vidioc_s_hw_freq_seek)break;type = (vfd->vfl_type == VFL_TYPE_RADIO) ?V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV;dbgarg(cmd,"tuner=%u, type=%u, seek_upward=%u, wrap_around=%u, spacing=%u\n",p->tuner, p->type, p->seek_upward, p->wrap_around, p->spacing);if (p->type != type)ret = -EINVAL;elseret = ops->vidioc_s_hw_freq_seek(file, fh, p);break;}case VIDIOC_ENUM_FRAMESIZES:{struct v4l2_frmsizeenum *p = arg;if (!ops->vidioc_enum_framesizes)break;ret = ops->vidioc_enum_framesizes(file, fh, p);dbgarg(cmd,"index=%d, pixelformat=%c%c%c%c, type=%d ",p->index,(p->pixel_format & 0xff),(p->pixel_format >> 8) & 0xff,(p->pixel_format >> 16) & 0xff,(p->pixel_format >> 24) & 0xff,p->type);switch (p->type) {case V4L2_FRMSIZE_TYPE_DISCRETE:dbgarg3("width = %d, height=%d\n",p->discrete.width, p->discrete.height);break;case V4L2_FRMSIZE_TYPE_STEPWISE:dbgarg3("min %dx%d, max %dx%d, step %dx%d\n",p->stepwise.min_width, p->stepwise.min_height,p->stepwise.step_width, p->stepwise.step_height,p->stepwise.max_width, p->stepwise.max_height);break;case V4L2_FRMSIZE_TYPE_CONTINUOUS:dbgarg3("continuous\n");break;default:dbgarg3("- Unknown type!\n");}break;}case VIDIOC_ENUM_FRAMEINTERVALS:{struct v4l2_frmivalenum *p = arg;if (!ops->vidioc_enum_frameintervals)break;ret = ops->vidioc_enum_frameintervals(file, fh, p);dbgarg(cmd,"index=%d, pixelformat=%d, width=%d, height=%d, type=%d ",p->index, p->pixel_format,p->width, p->height, p->type);switch (p->type) {case V4L2_FRMIVAL_TYPE_DISCRETE:dbgarg2("fps=%d/%d\n",p->discrete.numerator,p->discrete.denominator);break;case V4L2_FRMIVAL_TYPE_STEPWISE:dbgarg2("min=%d/%d, max=%d/%d, step=%d/%d\n",p->stepwise.min.numerator,p->stepwise.min.denominator,p->stepwise.max.numerator,p->stepwise.max.denominator,p->stepwise.step.numerator,p->stepwise.step.denominator);break;case V4L2_FRMIVAL_TYPE_CONTINUOUS:dbgarg2("continuous\n");break;default:dbgarg2("- Unknown type!\n");}break;}case VIDIOC_ENUM_DV_PRESETS:{struct v4l2_dv_enum_preset *p = arg;if (!ops->vidioc_enum_dv_presets)break;ret = ops->vidioc_enum_dv_presets(file, fh, p);if (!ret)dbgarg(cmd,"index=%d, preset=%d, name=%s, width=%d,"" height=%d ",p->index, p->preset, p->name, p->width,p->height);break;}case VIDIOC_S_DV_PRESET:{struct v4l2_dv_preset *p = arg;if (!ops->vidioc_s_dv_preset)break;dbgarg(cmd, "preset=%d\n", p->preset);ret = ops->vidioc_s_dv_preset(file, fh, p);break;}case VIDIOC_G_DV_PRESET:{struct v4l2_dv_preset *p = arg;if (!ops->vidioc_g_dv_preset)break;ret = ops->vidioc_g_dv_preset(file, fh, p);if (!ret)dbgarg(cmd, "preset=%d\n", p->preset);break;}case VIDIOC_QUERY_DV_PRESET:{struct v4l2_dv_preset *p = arg;if (!ops->vidioc_query_dv_preset)break;ret = ops->vidioc_query_dv_preset(file, fh, p);if (!ret)dbgarg(cmd, "preset=%d\n", p->preset);break;}case VIDIOC_S_DV_TIMINGS:{struct v4l2_dv_timings *p = arg;if (!ops->vidioc_s_dv_timings)break;switch (p->type) {case V4L2_DV_BT_656_1120:dbgarg2("bt-656/1120:interlaced=%d, pixelclock=%lld,"" width=%d, height=%d, polarities=%x,"" hfrontporch=%d, hsync=%d, hbackporch=%d,"" vfrontporch=%d, vsync=%d, vbackporch=%d,"" il_vfrontporch=%d, il_vsync=%d,"" il_vbackporch=%d\n",p->bt.interlaced, p->bt.pixelclock,p->bt.width, p->bt.height, p->bt.polarities,p->bt.hfrontporch, p->bt.hsync,p->bt.hbackporch, p->bt.vfrontporch,p->bt.vsync, p->bt.vbackporch,p->bt.il_vfrontporch, p->bt.il_vsync,p->bt.il_vbackporch);ret = ops->vidioc_s_dv_timings(file, fh, p);break;default:dbgarg2("Unknown type %d!\n", p->type);break;}break;}case VIDIOC_G_DV_TIMINGS:{struct v4l2_dv_timings *p = arg;if (!ops->vidioc_g_dv_timings)break;ret = ops->vidioc_g_dv_timings(file, fh, p);if (!ret) {switch (p->type) {case V4L2_DV_BT_656_1120:dbgarg2("bt-656/1120:interlaced=%d,"" pixelclock=%lld,"" width=%d, height=%d, polarities=%x,"" hfrontporch=%d, hsync=%d,"" hbackporch=%d, vfrontporch=%d,"" vsync=%d, vbackporch=%d,"" il_vfrontporch=%d, il_vsync=%d,"" il_vbackporch=%d\n",p->bt.interlaced, p->bt.pixelclock,p->bt.width, p->bt.height,p->bt.polarities, p->bt.hfrontporch,p->bt.hsync, p->bt.hbackporch,p->bt.vfrontporch, p->bt.vsync,p->bt.vbackporch, p->bt.il_vfrontporch,p->bt.il_vsync, p->bt.il_vbackporch);break;default:dbgarg2("Unknown type %d!\n", p->type);break;}}break;}case VIDIOC_DQEVENT:{struct v4l2_event *ev = arg;if (!ops->vidioc_subscribe_event)break;ret = v4l2_event_dequeue(fh, ev, file->f_flags & O_NONBLOCK);if (ret < 0) {dbgarg(cmd, "no pending events?");break;}dbgarg(cmd, "pending=%d, type=0x%8.8x, sequence=%d, " "timestamp=%lu.%9.9lu ", ev->pending, ev->type, ev->sequence, ev->timestamp.tv_sec, ev->timestamp.tv_nsec);break;}case VIDIOC_SUBSCRIBE_EVENT:{struct v4l2_event_subscription *sub = arg;if (!ops->vidioc_subscribe_event)break;ret = ops->vidioc_subscribe_event(fh, sub);if (ret < 0) {dbgarg(cmd, "failed, ret=%ld", ret);break;}dbgarg(cmd, "type=0x%8.8x", sub->type);break;}case VIDIOC_UNSUBSCRIBE_EVENT:{struct v4l2_event_subscription *sub = arg;if (!ops->vidioc_unsubscribe_event)break;ret = ops->vidioc_unsubscribe_event(fh, sub);if (ret < 0) {dbgarg(cmd, "failed, ret=%ld", ret);break;}dbgarg(cmd, "type=0x%8.8x", sub->type);break;}default:{bool valid_prio = true;if (!ops->vidioc_default)break;if (use_fh_prio)valid_prio = v4l2_prio_check(vfd->prio, vfh->prio) >= 0;ret = ops->vidioc_default(file, fh, valid_prio, cmd, arg);break;}} /* switch */exit_prio:if (vfd->debug & V4L2_DEBUG_IOCTL_ARG) {if (ret < 0) {v4l_print_ioctl(vfd->name, cmd);printk(KERN_CONT " error %ld\n", ret);}}return ret;}可以看出iotcl中的那些不同函数在这里依据cmd会被调用。所以这个ioctl核心就在video_ioctl2函数。具体这个函数在哪里被调用,等后面的分析。
阅读全文
0 0
- v4l2 ioctl框架分析
- V4L2 框架分析
- V4L2框架分析学习
- V4L2框架分析学习
- V4L2框架分析学习
- V4L2框架分析学习
- V4L2框架分析学习
- V4L2框架分析学习
- V4L2核心框架分析
- V4L2框架分析学习
- V4L2框架分析
- V4L2框架分析学习
- v4l2框架分析
- V4L2框架分析
- V4L2框架分析学习
- V4L2框架分析学习
- V4L2框架分析学习
- V4L2核心框架分析
- 学生信息管理系统知识点
- python实现-字符串最后一个单词的长度
- java泛型
- javaseday28(Swing 插件 做个小界面)
- 遇到的问题---百度ueditor----An error occurred at line: 12 in the jsp file: /ueditor/jsp/controller.jsp
- v4l2 ioctl框架分析
- 矩阵快速幂
- oracle10g提示“身份证明检索失败”
- 关于顺序数组求最大差值或最大收益算法
- ubuntu14 上安装tensorflow 遇到的问题
- 数据结构之栈、队列算法
- 【51Nod1241】 特殊的排序
- C#基础-006if条件语句
- Numpy_tile函数(kNN算法)