tuner-core.c: i2c tv tuner chip device driver.
/*
* This driver supports many devices and the idea is to let the driver
* detect which device is present. So rather than listing all supported
* devices here, we pretend to support a single, fake device type that will
* handle both radio and analog TV tuning.
* /
v4l2-async.c: v4l2子设备之间异步注册接口。
v4l2-clk.c: v4l2的时钟操作接口,提供接口来配置设备时钟。
v4l2-common.c:v4l2通用底层接口。
v4l2-compat-ioctl32.c:提供32位ioctl回调函数供v4l2-dev调用。
v4l2-ctrls.c:v4l2控制框架实现。
v4l2-dev.c:v4l2核心代码,驱动入口。以及cdev的fops实现。
v4l2-device.c:v4l2关于v4l2_device的相关接口。注册、绑定subdev等。
v4l2-dv-timings.c: dv-timings helper functions
v4l2-event.c:event事件订阅和处理接口。
v4l2-fh.c:v4l2 file handles基础接口。
用到file handle的文件:
file->private_data
中获取,主要用了它的ctrl_handler成员。file->private_data
中获取,主要用了它的event和ctrl_handler成员。file->private_data
中获取,主要是把fh当作入参传入用户自定义的ops回调。file->private_data
中获取,只用了其中的m2m_ctx成员file->private_data
中获取,用来配置ctrl_handler和eventv4l2-flash-led-class.c:flash LED驱动,包含subdev,media,ctrl, async功能。
v4l2-fwnode.c:以v4l2规定的dts格式parse对应节点。
v4l2-i2c.c:给v4l2_dev创建一个i2c的subdev
v4l2-ioctl.c: export一个ioctl接口,调用注册video_device时注册到vfd->ioctl_ops
中的相应回调。
v4l2-mc.c:v4l2框架对media框架的封装,主要是创建media graph以及对graph里面节点的pm操作。
v4l2-mem2mem.c:这是被实现video设备驱动调用的,它负责内存的管理。记住,它只是一个中间的管理者,因为真正分配内存的不是mem2mem,而是videobuf2。
v4l2-spi.c:给v4l2_dev创建一个spi 的subdev
v4l2-subdev.c:v4l2子设备相关接口。
v4l2-trace.c:只有几个接口:
EXPORT_TRACEPOINT_SYMBOL_GPL(vb2_v4l2_buf_done);
EXPORT_TRACEPOINT_SYMBOL_GPL(vb2_v4l2_buf_queue);
EXPORT_TRACEPOINT_SYMBOL_GPL(vb2_v4l2_dqbuf);
EXPORT_TRACEPOINT_SYMBOL_GPL(vb2_v4l2_qbuf);
videobuf-core.c:对以下三个文件的封装,为用户驱动程序提供内存操作接口。
videobuf-dma-contig.c
videobuf-dma-sg.c
videobuf-vmalloc.c
asd_list:v4l2_async_subdev链表
v4l2_dev:Notifier所在的v4l2_dev
struct v4l2_async_notifier {
const struct v4l2_async_notifier_operations *ops;
struct v4l2_device *v4l2_dev;
struct v4l2_subdev *sd;
struct v4l2_async_notifier *parent;
struct list_head asd_list;
struct list_head waiting;
struct list_head done;
struct list_head list;
};
match_type:async subdev的匹配模式
match:async subdev匹配时方法。有如下几种:
!strcmp(asd->match.device_name, dev_name(sd->dev));
struct v4l2_async_subdev {
enum v4l2_async_match_type match_type;
union {
struct fwnode_handle *fwnode;
const char *device_name;
struct {
int adapter_id;
unsigned short address;
} i2c;
struct {
bool (*match)(struct device *dev,
struct v4l2_async_subdev *sd);
void *priv;
} custom;
} match;
/* v4l2-async core private: not to be used by drivers */
struct list_head list;
struct list_head asd_list;
};
complete:当所有的subdev被probed会调用此接口,只有root notifier的complete接口会被调用。
struct v4l2_async_notifier_operations {
int (*bound)(struct v4l2_async_notifier *notifier,
struct v4l2_subdev *subdev,
struct v4l2_async_subdev *asd);
int (*complete)(struct v4l2_async_notifier *notifier);
void (*unbind)(struct v4l2_async_notifier *notifier,
struct v4l2_subdev *subdev,
struct v4l2_async_subdev *asd);
};
v4l2_async_notifier_init
初始化asd_list
v4l2_async_match_notify
v4l2_device_register_subdev
将subdev注册到v4l2框架v4l2_async_notifier_try_all_subdevs
从注册到async框架的subdev和notifier->waiting里面找到匹配的asd和subdev,然后调用v4l2_async_match_notify
将两者绑定到一起。
需要注意的是,subdev和asd不一定是一一对应的,只需要按照匹配规则,能匹配起来就会绑定到一起,可能多个subdev绑定一个asd。
v4l2_async_notifier_register
注册notifier到v4l2_dev。
notifier->asd_list
,判断asd是否有效,并将其加入到waiting列表中v4l2_async_notifier_try_all_subdevs
将所有注册到async框架的subdev和asd绑定起来v4l2_async_subdev_notifier_register
v4l2_async_notifier_unregister
取消绑定所有subdev和asd,并将subdev加入到async框架的subdev列表。
v4l2_async_register_subdev
如果此时没有注册notifier,那么将这个subdev加入到async框架的subdev列表中;
如果此时已经注册过notifier了,那么选择合适的notifier下waiting列表的asd,完成绑定,并将这个subdev加入到async框架的subdev列表中。
v4l2_async_notifier_cleanup
清理notifier下的asd列表
v4l2_async_notifier_add_subdev
往notifier上添加asd,作为匹配subdev的条件。
v4l2_async_notifier_add_fwnode_subdev
往notifier上添加fwnode格式的asd,作为匹配subdev的条件。
v4l2_async_notifier_add_fwnode_remote_subdev
往notifier上添加fwnode格式的asd,remote node作为匹配subdev的条件。
v4l2_async_notifier_add_i2c_subdev
往notifier上添加i2c格式的asd,作为匹配subdev的条件。
v4l2_async_notifier_add_devname_subdev
往notifier上添加devname格式的asd,作为匹配subdev的条件。
v4l2_compat_ioctl32:作为v4l2-device的ioctl32回调。如果cmd是v4l2定义的控制字,则调用do_video_ioctl
,如果是用户自定义的控制字,则调用用户自定义的ioctl回调。
videodev_init
驱动入口函数,创建v4l2的class,分配cdev的主设备号,videoX设备节点是在__video_register_device
函数中被创建的。
__video_register_device
根据不同的设备类型,创建不同的cdev设备节点。
设备类型包括:
VFL_TYPE_GRABBER: “video”
VFL_TYPE_VBI: “vbi”
VFL_TYPE_RADIO: “radio”
VFL_TYPE_SUBDEV: “v4l-subdev”
VFL_TYPE_SDR: “swradio”
VFL_TYPE_TOUCH: “v4l-touch”
在注册video device的时候,会把v4l2_fops注册进去,v4l2_fops会回调video device的fops和ioctl_ops,这些ops是在创建video device时,由驱动实现并指定的。
video_device_alloc
分配一个空的video device结构体
v4l2_device_register
初始化v4l2_dev上下文
v4l2_device_release
释放v4l2_dev
v4l2_device_set_name
设置v4l2_dev的名字
v4l2_device_disconnect
解除v4l2_dev与对应dev的绑定
v4l2_device_unregister
v4l2_device_register_subdev
向v4l2_dev注册subdev
会检查如下参数:
/* Check for valid input */
if (!v4l2_dev || !sd || sd->v4l2_dev || !sd->name[0])
return -EINVAL;
v4l2_subdev_release
释放subdev
v4l2_device_register_subdev_nodes
为v4l2_dev下所有的subdev注册node节点(如果配置为生成节点的模式的话)
v4l2_device_unregister_subdev
unregister subdev
struct v4l2_kevent {
struct list_head list;
struct v4l2_subscribed_event *sev;
struct v4l2_event event;
u64 ts;
};
struct v4l2_subscribed_event {
struct list_head list;
u32 type;
u32 id;
u32 flags;
struct v4l2_fh *fh;
struct list_head node;
const struct v4l2_subscribed_event_ops *ops;
unsigned int elems;
unsigned int first;
unsigned int in_use;
struct v4l2_kevent events[];
};
v4l2_event_dequeue
分为阻塞和非阻塞两种情况:
__v4l2_event_dequeue
从fh->available
列表中取可用的eventfh->wait
信号量,被唤醒后再调用__v4l2_event_dequeue
从fh->available
列表中取可用的eventv4l2_event_queue
需要用到:ev->type, ev->id
fh->subscribed
列表中获取sevfh->available
列表fh->wait
信号量v4l2_event_queue_fh
参考v4l2_event_queue
实现,不过入参不是video device而是fh
v4l2_event_pending
返回就绪的event的数量
v4l2_event_subscribe
根据驱动传入的event类型和event深度,创建sev结构体,并将其加入到fh->subscribed
列表中
v4l2_event_unsubscribe_all
取消订阅所有event
v4l2_event_unsubscribe
移除指定type和id的订阅
v4l2_src_change_event_subscribe
订阅source change类型的event
v4l2_src_change_event_subdev_subscribe
取消订阅source change类型的event
从下图可以看出,event的订阅和通知都是基于fh的,也就是说用户下发订阅是以fh为单位,通知用户也是以fh为单位。用户态在open video节点之后,基于这个fd进行event的订阅与通知。
参考链接: media controller framework
v4l2_subdev_link_validate_default
默认的检查两个subdev link有效的接口
v4l2_subdev_link_validate
检查link的source和sink是否匹配,如果有用户自定义检查接口,就调用用户自定义接口,否则调用上面的默认接口。
v4l2_subdev_alloc_pad_config
v4l2_subdev_init
初始化subdev上下文
v4l2_subdev_notify_event
将对应的event通知到subdev下的订阅列表中
subdev的ops在调用v4l2_subdev_init函数时指定,包含以下ops:
/**
* struct v4l2_subdev_ops - Subdev operations
*
* @core: pointer to &struct v4l2_subdev_core_ops. Can be %NULL
* @tuner: pointer to &struct v4l2_subdev_tuner_ops. Can be %NULL
* @audio: pointer to &struct v4l2_subdev_audio_ops. Can be %NULL
* @video: pointer to &struct v4l2_subdev_video_ops. Can be %NULL
* @vbi: pointer to &struct v4l2_subdev_vbi_ops. Can be %NULL
* @ir: pointer to &struct v4l2_subdev_ir_ops. Can be %NULL
* @sensor: pointer to &struct v4l2_subdev_sensor_ops. Can be %NULL
* @pad: pointer to &struct v4l2_subdev_pad_ops. Can be %NULL
*/
struct v4l2_subdev_ops {
const struct v4l2_subdev_core_ops *core;
const struct v4l2_subdev_tuner_ops *tuner;
const struct v4l2_subdev_audio_ops *audio;
const struct v4l2_subdev_video_ops *video;
const struct v4l2_subdev_vbi_ops *vbi;
const struct v4l2_subdev_ir_ops *ir;
const struct v4l2_subdev_sensor_ops *sensor;
const struct v4l2_subdev_pad_ops *pad;
};
其中,内部的分类ops如下:
struct v4l2_subdev_core_ops {
int (*log_status)(struct v4l2_subdev *sd);
int (*s_io_pin_config)(struct v4l2_subdev *sd, size_t n,
struct v4l2_subdev_io_pin_config *pincfg);
int (*init)(struct v4l2_subdev *sd, u32 val);
int (*load_fw)(struct v4l2_subdev *sd);
int (*reset)(struct v4l2_subdev *sd, u32 val);
int (*s_gpio)(struct v4l2_subdev *sd, u32 val);
long (*command)(struct v4l2_subdev *sd, unsigned int cmd, void *arg);
long (*ioctl)(struct v4l2_subdev *sd, unsigned int cmd, void *arg);
#ifdef CONFIG_COMPAT
long (*compat_ioctl32)(struct v4l2_subdev *sd, unsigned int cmd,
unsigned long arg);
#endif
#ifdef CONFIG_VIDEO_ADV_DEBUG
int (*g_register)(struct v4l2_subdev *sd, struct v4l2_dbg_register *reg);
int (*s_register)(struct v4l2_subdev *sd, const struct v4l2_dbg_register *reg);
#endif
int (*s_power)(struct v4l2_subdev *sd, int on);
int (*interrupt_service_routine)(struct v4l2_subdev *sd,
u32 status, bool *handled);
int (*subscribe_event)(struct v4l2_subdev *sd, struct v4l2_fh *fh,
struct v4l2_event_subscription *sub);
int (*unsubscribe_event)(struct v4l2_subdev *sd, struct v4l2_fh *fh,
struct v4l2_event_subscription *sub);
};
struct v4l2_subdev_tuner_ops {
int (*standby)(struct v4l2_subdev *sd);
int (*s_radio)(struct v4l2_subdev *sd);
int (*s_frequency)(struct v4l2_subdev *sd, const struct v4l2_frequency *freq);
int (*g_frequency)(struct v4l2_subdev *sd, struct v4l2_frequency *freq);
int (*enum_freq_bands)(struct v4l2_subdev *sd, struct v4l2_frequency_band *band);
int (*g_tuner)(struct v4l2_subdev *sd, struct v4l2_tuner *vt);
int (*s_tuner)(struct v4l2_subdev *sd, const struct v4l2_tuner *vt);
int (*g_modulator)(struct v4l2_subdev *sd, struct v4l2_modulator *vm);
int (*s_modulator)(struct v4l2_subdev *sd, const struct v4l2_modulator *vm);
int (*s_type_addr)(struct v4l2_subdev *sd, struct tuner_setup *type);
int (*s_config)(struct v4l2_subdev *sd, const struct v4l2_priv_tun_config *config);
};
struct v4l2_subdev_audio_ops {
int (*s_clock_freq)(struct v4l2_subdev *sd, u32 freq);
int (*s_i2s_clock_freq)(struct v4l2_subdev *sd, u32 freq);
int (*s_routing)(struct v4l2_subdev *sd, u32 input, u32 output, u32 config);
int (*s_stream)(struct v4l2_subdev *sd, int enable);
};
struct v4l2_subdev_vbi_ops {
int (*decode_vbi_line)(struct v4l2_subdev *sd, struct v4l2_decode_vbi_line *vbi_line);
int (*s_vbi_data)(struct v4l2_subdev *sd, const struct v4l2_sliced_vbi_data *vbi_data);
int (*g_vbi_data)(struct v4l2_subdev *sd, struct v4l2_sliced_vbi_data *vbi_data);
int (*g_sliced_vbi_cap)(struct v4l2_subdev *sd, struct v4l2_sliced_vbi_cap *cap);
int (*s_raw_fmt)(struct v4l2_subdev *sd, struct v4l2_vbi_format *fmt);
int (*g_sliced_fmt)(struct v4l2_subdev *sd, struct v4l2_sliced_vbi_format *fmt);
int (*s_sliced_fmt)(struct v4l2_subdev *sd, struct v4l2_sliced_vbi_format *fmt);
};
struct v4l2_subdev_ir_ops {
/* Receiver */
int (*rx_read)(struct v4l2_subdev *sd, u8 *buf, size_t count,
ssize_t *num);
int (*rx_g_parameters)(struct v4l2_subdev *sd,
struct v4l2_subdev_ir_parameters *params);
int (*rx_s_parameters)(struct v4l2_subdev *sd,
struct v4l2_subdev_ir_parameters *params);
/* Transmitter */
int (*tx_write)(struct v4l2_subdev *sd, u8 *buf, size_t count,
ssize_t *num);
int (*tx_g_parameters)(struct v4l2_subdev *sd,
struct v4l2_subdev_ir_parameters *params);
int (*tx_s_parameters)(struct v4l2_subdev *sd,
struct v4l2_subdev_ir_parameters *params);
};
struct v4l2_subdev_sensor_ops {
int (*g_skip_top_lines)(struct v4l2_subdev *sd, u32 *lines);
int (*g_skip_frames)(struct v4l2_subdev *sd, u32 *frames);
};
struct v4l2_subdev_pad_ops {
int (*init_cfg)(struct v4l2_subdev *sd,
struct v4l2_subdev_pad_config *cfg);
int (*enum_mbus_code)(struct v4l2_subdev *sd,
struct v4l2_subdev_pad_config *cfg,
struct v4l2_subdev_mbus_code_enum *code);
int (*enum_frame_size)(struct v4l2_subdev *sd,
struct v4l2_subdev_pad_config *cfg,
struct v4l2_subdev_frame_size_enum *fse);
int (*enum_frame_interval)(struct v4l2_subdev *sd,
struct v4l2_subdev_pad_config *cfg,
struct v4l2_subdev_frame_interval_enum *fie);
int (*get_fmt)(struct v4l2_subdev *sd,
struct v4l2_subdev_pad_config *cfg,
struct v4l2_subdev_format *format);
int (*set_fmt)(struct v4l2_subdev *sd,
struct v4l2_subdev_pad_config *cfg,
struct v4l2_subdev_format *format);
int (*get_selection)(struct v4l2_subdev *sd,
struct v4l2_subdev_pad_config *cfg,
struct v4l2_subdev_selection *sel);
int (*set_selection)(struct v4l2_subdev *sd,
struct v4l2_subdev_pad_config *cfg,
struct v4l2_subdev_selection *sel);
int (*get_edid)(struct v4l2_subdev *sd, struct v4l2_edid *edid);
int (*set_edid)(struct v4l2_subdev *sd, struct v4l2_edid *edid);
int (*dv_timings_cap)(struct v4l2_subdev *sd,
struct v4l2_dv_timings_cap *cap);
int (*enum_dv_timings)(struct v4l2_subdev *sd,
struct v4l2_enum_dv_timings *timings);
#ifdef CONFIG_MEDIA_CONTROLLER
int (*link_validate)(struct v4l2_subdev *sd, struct media_link *link,
struct v4l2_subdev_format *source_fmt,
struct v4l2_subdev_format *sink_fmt);
#endif /* CONFIG_MEDIA_CONTROLLER */
int (*get_frame_desc)(struct v4l2_subdev *sd, unsigned int pad,
struct v4l2_mbus_frame_desc *fd);
int (*set_frame_desc)(struct v4l2_subdev *sd, unsigned int pad,
struct v4l2_mbus_frame_desc *fd);
};
subdev的ops调用流程:
v4l2_subdev_init
时传入用户自定义subdev_ops,框架会将ops配置到subdev的结构体中。v4l2_subdev_ops
v4l2_device_register_subdev_nodes
函数时,会遍历v4l2_dev下面所有的subdev节点,将此节点生成一个subdev node到用户态。v4l2_device_register_subdev_nodes
函数会调用__video_register_device
函数创建subdev节点,在此之前,v4l2_subdev_fops
变量配置到vdev的fops成员里。__video_register_device
函数创建subdev节点是通过cdev_add添加的,用户态节点第一个调用的函数其实是v4l2_fops.read/write/ioctl()
,在v4l2_fops.read/write/ioctl()
中再回调vdev->fops.read/write/ioctl()
也就是v4l2_subdev_fops
。v4l2_subdev_fops
里面的unlocked_ioctl会调用subdev_do_ioctl
,里面会从file结构体中解析出subdev结构体,进而获取到用户自定义opsvideo device的ops调用流程与subdev的调用流程相似,区别在于,在调用video_register_device
函数时,需要用户自定义fops与ioctl_ops,以实现用户自定义的功能。
其中,ioctl_ops被fops.unlocked_ioctl()
调用,以实现video device的视频控制功能。
ioctl_ops定义如下:
struct v4l2_ioctl_ops {
/* ioctl callbacks */
/* VIDIOC_QUERYCAP handler */
int (*vidioc_querycap)(struct file *file, void *fh,
struct v4l2_capability *cap);
/* 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_sdr_cap)(struct file *file, void *fh,
struct v4l2_fmtdesc *f);
int (*vidioc_enum_fmt_sdr_out)(struct file *file, void *fh,
struct v4l2_fmtdesc *f);
int (*vidioc_enum_fmt_meta_cap)(struct file *file, void *fh,
struct v4l2_fmtdesc *f);
int (*vidioc_enum_fmt_meta_out)(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_sdr_cap)(struct file *file, void *fh,
struct v4l2_format *f);
int (*vidioc_g_fmt_sdr_out)(struct file *file, void *fh,
struct v4l2_format *f);
int (*vidioc_g_fmt_meta_cap)(struct file *file, void *fh,
struct v4l2_format *f);
int (*vidioc_g_fmt_meta_out)(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_sdr_cap)(struct file *file, void *fh,
struct v4l2_format *f);
int (*vidioc_s_fmt_sdr_out)(struct file *file, void *fh,
struct v4l2_format *f);
int (*vidioc_s_fmt_meta_cap)(struct file *file, void *fh,
struct v4l2_format *f);
int (*vidioc_s_fmt_meta_out)(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_sdr_cap)(struct file *file, void *fh,
struct v4l2_format *f);
int (*vidioc_try_fmt_sdr_out)(struct file *file, void *fh,
struct v4l2_format *f);
int (*vidioc_try_fmt_meta_cap)(struct file *file, void *fh,
struct v4l2_format *f);
int (*vidioc_try_fmt_meta_out)(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_expbuf)(struct file *file, void *fh,
struct v4l2_exportbuffer *e);
int (*vidioc_dqbuf)(struct file *file, void *fh,
struct v4l2_buffer *b);
int (*vidioc_create_bufs)(struct file *file, void *fh,
struct v4l2_create_buffers *b);
int (*vidioc_prepare_buf)(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,
const 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 handling
*
* Note: ENUMSTD 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_query_ext_ctrl)(struct file *file, void *fh,
struct v4l2_query_ext_ctrl *a);
int (*vidioc_g_ctrl)(struct file *file, void *fh,
struct v4l2_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,
const 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,
const 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,
const struct v4l2_modulator *a);
/* Crop ioctls */
int (*vidioc_g_pixelaspect)(struct file *file, void *fh,
int buf_type, struct v4l2_fract *aspect);
int (*vidioc_g_selection)(struct file *file, void *fh,
struct v4l2_selection *s);
int (*vidioc_s_selection)(struct file *file, void *fh,
struct v4l2_selection *s);
/* Compression ioctls */
int (*vidioc_g_jpegcomp)(struct file *file, void *fh,
struct v4l2_jpegcompression *a);
int (*vidioc_s_jpegcomp)(struct file *file, void *fh,
const 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);
int (*vidioc_decoder_cmd)(struct file *file, void *fh,
struct v4l2_decoder_cmd *a);
int (*vidioc_try_decoder_cmd)(struct file *file, void *fh,
struct v4l2_decoder_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,
const 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,
const struct v4l2_frequency *a);
int (*vidioc_enum_freq_bands)(struct file *file, void *fh,
struct v4l2_frequency_band *band);
/* 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,
const struct v4l2_hw_freq_seek *a);
/* Debugging ioctls */
#ifdef CONFIG_VIDEO_ADV_DEBUG
int (*vidioc_g_register)(struct file *file, void *fh,
struct v4l2_dbg_register *reg);
int (*vidioc_s_register)(struct file *file, void *fh,
const struct v4l2_dbg_register *reg);
int (*vidioc_g_chip_info)(struct file *file, void *fh,
struct v4l2_dbg_chip_info *chip);
#endif
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_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_query_dv_timings)(struct file *file, void *fh,
struct v4l2_dv_timings *timings);
int (*vidioc_enum_dv_timings)(struct file *file, void *fh,
struct v4l2_enum_dv_timings *timings);
int (*vidioc_dv_timings_cap)(struct file *file, void *fh,
struct v4l2_dv_timings_cap *cap);
int (*vidioc_g_edid)(struct file *file, void *fh,
struct v4l2_edid *edid);
int (*vidioc_s_edid)(struct file *file, void *fh,
struct v4l2_edid *edid);
int (*vidioc_subscribe_event)(struct v4l2_fh *fh,
const struct v4l2_event_subscription *sub);
int (*vidioc_unsubscribe_event)(struct v4l2_fh *fh,
const struct v4l2_event_subscription *sub);
/* For other private ioctls */
long (*vidioc_default)(struct file *file, void *fh,
bool valid_prio, unsigned int cmd, void *arg);
};
v4l2 dev只有一个ops:v4l2_ops
,作为用户态设备节点往内核态调用的入口,调用对应设备节点 私有数据里面video device成员的fops。
链接: VB2在V4L2框架下的流程解读