虚拟摄像头驱动程序框架分析

虚拟摄像头驱动程序框架分析

        摄像头驱动程序可以归类为字符设备驱动程,所以摄像头的驱动程序可以根据字符设备驱动程序的框架来完成,由于摄像头驱动程序比较复杂,所以采用分层的框架来实现。

一、字符驱动程序的实现步骤:

1、申请device结构体

2、设置device结构体

3、注册device结构体

二、由此我们可以根据上面的步骤来实现虚拟摄像头的驱动程:

1、通过video_device_alloc函数分配一个video_device结构体

2、设置video_device结构体,后面详细介绍这个结构体关键的内容

3、通知video_register_device函数注册video_device结构体

我们来分析下video_device_alloc函数:

struct video_device *video_device_alloc ( void )
{
return kzalloc ( sizeof ( struct video_device ), GFP_KERNEL );
}


       这个函数比较简单,其实就是分配一个结构。Kzalloc很kmalloc的区别就是Kzalloc分配机构体后并且把它初始化为0。

       再看一看video_device结构体的主要内容如下:

struct video_device
{
#if defined (CONFIG_MEDIA_CONTROLLER )
struct media_entity entity ;
#endif
/* device ops */
const struct v4l2_file_operations *fops ;

/* sysfs */
struct device dev ; /* v4l device */
struct cdev *cdev ; /* character device */

/* Set either parent or v4l2_dev if your driver uses v4l2_device */
struct device *parent ; /* device parent */
struct v4l2_device *v4l2_dev ; /* v4l2_device parent */

/* Control handler associated with this device node. May be NULL. */
struct v4l2_ctrl_handler *ctrl_handler ;

/* Priority state. If NULL, then v4l2_dev->prio will be used. */
struct v4l2_prio_state *prio ;

/* device info */
char name [ 32] ;
int vfl_type ;
/* 'minor' is set to -1 if the registration failed */
int minor ;
u16 num ;
/* use bitops to set/clear/test flags */
unsigned long flags ;
/* attribute to differentiate multiple indices on one physical device */
int index ;

/* V4L2 file handles */
spinlock_t fh_lock ; /* Lock for all v4l2_fhs */
struct list_head fh_list ; /* List of struct v4l2_fh */

int debug ; /* Activates debug level*/

/* Video standard vars */
v4l2_std_id tvnorms ; /* Supported tv norms */
v4l2_std_id current_norm ; /* Current tvnorm */

/* callbacks */
void (*release )( struct video_device *vdev );

/* ioctl callbacks */
const struct v4l2_ioctl_ops *ioctl_ops ;

/* serialization lock */
struct mutex *lock ;
};


        其实比较重要的就是release、fops、ioctl_ops比较重要,别的我们都可以不管。Release对于我们自己写的release函数,fops对于我们自己写的v4l2_file_operations,ioctl_ops对于我们自己写的v4l2_ioctl_ops。实现v4l2_file_operations和v4l2_ioctl_ops非常重要。

三、分析v4l2_file_operations和v4l2_ioctl_ops结构体

         v4l2_file_operations结构体包含的内容如下:


struct v4l2_file_operations {
struct module *owner ;
ssize_t (*read ) ( struct file *, char __user *, size_t , loff_t *);
ssize_t (*write ) ( struct file *, const char __user *, size_t , loff_t *);
unsigned int (*poll ) ( struct file *, struct poll_table_struct *);
long (*ioctl ) ( struct file *, unsigned int , unsigned long );
long (*unlocked_ioctl ) ( struct file *, unsigned int , unsigned long );
#ifdef CONFIG_COMPAT
long (*compat_ioctl32 ) ( struct file *, unsigned int , unsigned long );
#endif
unsigned long (*get_unmapped_area ) ( struct file *, unsigned long ,
unsigned long , unsigned long , unsigned long );
int (*mmap ) ( struct file *, struct vm_area_struct *);
int (*open ) ( struct file *);
int (*release ) ( struct file *);
};

        然后这里面需要我们自己去填充的内容如下:

       Owner、open、release、mmap、ioctl、poll 可以参考vivi.c里面的函数去实现

       v4l2_ioctl_ops该结构体里面的函数用来设置摄像头的属性和获取摄像头的数据等,用于应用层掉用,结构体的内容如下:


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_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 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
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_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 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 );
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 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 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_DEBUG
int (*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 );
#endif
int (*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 );
};

        该结构体的内容非常多,我们可以参考vivi.c的代码,选择性的实现里面必要的函数,大概需要实现的函数如下:


static const struct v4l2_ioctl_ops myvivi_ioctl_ops = {
// 表示它是一个摄像头设备
.vidioc_querycap
/* 用于列举、获得、测试、设置摄像头的数据的格式 */
.vidioc_enum_fmt_vid_cap
.vidioc_g_fmt_vid_cap
.vidioc_try_fmt_vid_cap
.vidioc_s_fmt_vid_cap

/* 缓冲区操作: 申请/查询/放入队列/取出队列 */
.vidioc_reqbufs
.vidioc_querybuf
.vidioc_qbuf
.vidioc_dqbuf

// 启动/停止
.vidioc_streamon
.vidioc_streamoff
};

        上面的函数可以参考vivi.c里面的函数去实现。

        在这里虚拟摄像头的驱动程序的框架大致就是这样,后续再继续对结构体里面的内容进行详细分析。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值