V4L2 Driver-Overall architecture

Source: Internet
Author: User
Tags mutex

My UVC Open Source address: GITEE-UVC

    • Character device driver Core: V4l2 itself is a character device that has all the features of a character device, exposing the interface to user space.
    • V4L2 Drive Core: The main is to build a kernel in the standard video device driver framework, for video operations to provide a unified interface function.
    • Platform V4L2 device driver: Under the V4L2 framework, the platform-related V4L2 drivers are implemented according to the platform's own features, including registration Video_device and V4l2_dev.
    • Specific sensor driver: The main power-up, provide work clock, video image clipping, stream IO open, etc., to achieve a variety of device control methods for the upper call and register V4l2_subdev.
1 starting from the character device:

Familiar with V4L2 user space programming know, V4L2 programming is to call a series of IOCTL function to open, close, query, set up and so on v4l2 device. The V4L2 device is a character device, and its main driver is to implement a variety of IOCTL.

The overall framework of the V4L2 is as follows:

V4l2:video for Linux version 2 is a standard set of video drivers in Linux. This article is to analyze its core framework.

The implementation of this file_operations in the core of V4L2 is as follows:

static const struct file_operations v4l2_fops = {    .owner = THIS_MODULE,    .read = v4l2_read,    .write = v4l2_write,    .open = v4l2_open,    .get_unmapped_area = v4l2_get_unmapped_area,    .mmap = v4l2_mmap,    .unlocked_ioctl = v4l2_ioctl,#ifdef CONFIG_COMPAT    .compat_ioctl = v4l2_compat_ioctl32,#endif    .release = v4l2_release,    .poll = v4l2_poll,    .llseek = no_llseek,};

The V4l2_fops function is eventually bound to a Cdev and registered in the system.

v4l2_openas an example (code in kernel\drivers\media\v4l2-core ):

/* Override for the Open function */static int v4l2_open (struct inode *inode, struct file *filp) {struct VIDEO_DE Vice *vdev; int ret = 0; /* Check If the video device is available */Mutex_lock (&videodev_lock); Vdev = Video_devdata (FILP); /* Return ENODEV If the video device has already been removed. */if (Vdev = = NULL | |!video_is_registered (VDEV)) {Mutex_unlock (&videodev_lock); Return-enodev; }/* and increase the device RefCount */Video_get (VDEV); Mutex_unlock (&videodev_lock); if (Vdev->fops->open) {if (video_is_registered (Vdev))///This is the open function that calls File_operations ret = Vdev->fops->open (FILP); else ret =-enodev; } if (Vdev->debug) printk (kern_debug "%s:open (%d) \ n", Video_device_node_name (Vdev), ret); /* Decrease the refcount in case of an error */if (ret) video_put (Vdev); return ret;} 
2. Video_device structure:

The Video_device structure is used to generate the device node file in the/dev directory, exposing the interface of the operating device to the user space.

We use it video_device to manipulate and look at video_device the structure:

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 is NULL.    */struct V4l2_ctrl_handler *ctrl_handler; /* Vb2_queue associated with this device node. May is NULL.    */struct Vb2_queue *queue; /* Priority state. If NULL, then V4l2_dev->prio'll be used.    */struct v4l2_prio_state *prio;    /* Device Info */char name[32];   int vfl_type;    /* Device type */int vfl_dir;    /* receiver, transmitter or */*/*/* ' 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;    Declare_bitmap (Valid_ioctls, base_vidioc_private);    /* Serialization Lock */Declare_bitmap (disable_locking, base_vidioc_private); struct mutex *lock;};
3. V4l2_device Structure:

This structure contains a very important structure v4l2_device :

struct V4l2_device {/* Dev->driver_data points to the this struct. Note:dev might was NULL if there is no parent device as was the case with e.g. ISA devices.  */struct device *dev; #if defined (config_media_controller) struct media_device *mdev; #endif/* Used to keep track    of the registered Subdevs */struct list_head Subdevs; /* lock this struct; Can be used by the driver as well if this struct was embedded into a larger struct.    */spinlock_t lock;    /* Unique device name, by default the driver name + bus ID */char name[v4l2_device_name_size]; /* Notify callback called by some sub-devices.    */void (*notify) (struct V4l2_subdev *sd, unsigned int notification, void *arg); /* The control handler. May is NULL.    */struct V4l2_ctrl_handler *ctrl_handler;    /* Device ' s priority state */struct v4l2_prio_state prio; /* BKL replacement mutex. Temporary solution only.    */struct Mutex ioctl_lock; /* Keep track of the refErences to this struct.    */struct KREF ref; /* Release function that's called when the ref count goes to 0. */void (*release) (struct v4l2_device *v4l2_dev);};
Registration and deregistration of 3.1 V4l2_device:
int v4l2_device_register(struct device*dev, struct v4l2_device *v4l2_dev)static void v4l2_device_release(struct kref *ref)
4. V4l2_subdev Structural Body

V4l2_subdev represents a sub-device that contains related properties and operations for a child device. First look at the structure prototype:

struct v4l2_subdev {          struct v4l2_device *v4l2_dev;  //指向父设备          //提供一些控制v4l2设备的接口          const struct v4l2_subdev_ops *ops;          //向V4L2框架提供的接口函数          const struct v4l2_subdev_internal_ops *internal_ops;          //subdev控制接口          struct v4l2_ctrl_handler *ctrl_handler;          /* name must be unique */          charname[V4L2_SUBDEV_NAME_SIZE];          /*subdev device node */          struct video_device *devnode;   };

Where the list field is linked to the v4l2_device structure pointed to by V4l2_dev as a linked list node, the most important member of this structure is the struct v4l2_subdev_ops *ops, which contains all the operations supported by the V4L2 device, defined as follows:

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;  /* 视频操作合集 */};

V4l2_subdev_core_ops contains operation collections that are common to various types of devices:

struct V4l2_subdev_core_ops {int (*g_chip_ident) (struct V4l2_subdev *sd, struct v4l2_dbg_chip_ident *chip);                                      /* Get Device ID */INT (*log_status) (struct V4l2_subdev *sd);          /* Status message */INT (*s_config) (struct v4l2_subdev *sd, int irq, void *platform_data);                                   /* Set Configuration information */INT (*init) (struct V4l2_subdev *sd, u32 val);                                         /* Initialize the device */int (*LOAD_FW) (struct V4l2_subdev *sd);                                  /* Load firmware */INT (*reset) (struct V4l2_subdev *sd, u32 val);                                 /* Reset device */int (*s_gpio) (struct V4l2_subdev *sd, u32 val);            /* Set GPIO */INT (*queryctrl) (struct V4l2_subdev *sd, struct V4l2_queryctrl *qc);               /* query Device supported operation */INT (*g_ctrl) (struct V4l2_subdev *sd, struct V4l2_control *ctrl);               /* Get current command value */INT (*s_ctrl) (struct V4l2_subdev *sd, struct V4l2_control *ctrl); /* Set current command value */INT (*g_ext_ctrls)    (struct V4l2_subdev *sd, struct v4l2_ext_controls *ctrls);    /* Get External command value */INT (*s_ext_ctrls) (struct V4l2_subdev *sd, struct v4l2_ext_controls *ctrls);    /* Set the external command value */INT (*try_ext_ctrls) (struct V4l2_subdev *sd, struct v4l2_ext_controls *ctrls);            Int (*querymenu) (struct V4l2_subdev *sd, struct v4l2_querymenu *qm);                         /* Query Action menu */INT (*S_STD) (struct V4l2_subdev *sd, v4l2_std_id norm);             /* Set Data Standard */Long (*IOCTL) (struct V4l2_subdev *sd, unsigned int cmd, void *arg);       /* Handle SPECIAL commands */#ifdef config_video_adv_debug int (*g_register) (struct V4l2_subdev *sd, struct v4l2_dbg_register *reg);       /* Get Register value */INT (*s_register) (struct V4l2_subdev *sd, struct v4l2_dbg_register *reg); /* Set Register value */#endif};

The

V4l2_subdev_tuner_ops contains a collection of actions that are unique to the tuner:

struct V4l2_subdev_tuner_ops {int (*s_mode) (struct V4l2_subdev *sd, enum V4l2_tuner_type);                                    /* Set Tuner mode */INT (*s_radio) (struct V4l2_subdev *sd);   /* Set the wireless device information */INT (*s_frequency) (struct V4l2_subdev *sd, struct v4l2_frequency *freq);   /* Set frequency */INT (*g_frequency) (struct V4l2_subdev *sd, struct v4l2_frequency *freq);             /* Get frequency */INT (*g_tuner) (struct V4l2_subdev *sd, struct v4l2_tuner *vt);             /* Get tuner information */INT (*s_tuner) (struct V4l2_subdev *sd, struct v4l2_tuner *vt);     /* Set TUNER information */INT (*g_modulator) (struct V4l2_subdev *sd, struct v4l2_modulator *vm);     /* Get the amplitude modulation information */INT (*s_modulator) (struct V4l2_subdev *sd, struct v4l2_modulator *vm);      /* Set the amplitude modulation information */INT (*s_type_addr) (struct V4l2_subdev *sd, struct tuner_setup *type);   /* Install tuner */INT (*s_config) (struct V4l2_subdev *sd, const struct v4l2_priv_tun_config *config);  /* Set Configuration information */INT (*s_standby) (struct V4l2_subdev *sd);                                /* Set standard */}; 

The v4l2_subdev_audio_ops contains an operation collection that is unique to the audio section:

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);   /* 设置i2s总线频率 */    int (*s_routing)(struct v4l2_subdev *sd, u32 input, u32 output, u32 config);   /* 设置音频路由 */};

The V4l2_subdev_video_ops contains a collection of actions that are unique to the video section:

struct V4l2_subdev_video_ops {int (*s_routing) (struct V4l2_subdev *sd, u32 input, u32 output, u32 config);                      /* Set the video route */INT (*s_crystal_freq) (struct V4l2_subdev *sd, u32 freq, u32 flags);   /* Set Device frequency */INT (*decode_vbi_line) (struct V4l2_subdev *sd, struct v4l2_decode_vbi_line *vbi_line);  /* Blanking Area information decoding */INT (*s_vbi_data) (struct V4l2_subdev *sd, const struct v4l2_sliced_vbi_data *vbi_data);        /* Set the blanking area data */INT (*g_vbi_data) (struct V4l2_subdev *sd, struct v4l2_sliced_vbi_data *vbi_data);    /* The hidden Data is canceled */int (*g_sliced_vbi_cap) (struct V4l2_subdev *sd, struct v4l2_sliced_vbi_cap *cap);                            Int (*s_std_output) (struct V4l2_subdev *sd, v4l2_std_id std);                               /* Set standard OUTPUT */int (*QUERYSTD) (struct V4l2_subdev *sd, v4l2_std_id *std);                              /* Query standard */INT (*g_input_status) (struct V4l2_subdev *sd, u32 *status); /* Get INPUT status */INT (*s_stream) (struct V4l2_subdev *sd,int enable);                   /* Set Data Flow */INT (*enum_fmt) (struct V4l2_subdev *sd, struct v4l2_fmtdesc *fmtdesc);                           /* Enumerate video formats */INT (*g_fmt) (struct V4l2_subdev *sd, struct v4l2_format *fmt);                         /* Get the video format */int (*try_fmt) (struct V4l2_subdev *sd, struct v4l2_format *fmt);                           /* Try to set the video format */int (*s_fmt) (struct V4l2_subdev *sd, struct v4l2_format *fmt);                         /* Set Video format */int (*cropcap) (struct V4l2_subdev *sd, struct v4l2_cropcap *cc);                           /* Video clip function */int (*g_crop) (struct V4l2_subdev *sd, struct v4l2_crop *crop);                           /* Get Clip function */int (*s_crop) (struct V4l2_subdev *sd, struct v4l2_crop *crop);                    /* Set Clip function */int (*g_parm) (struct V4l2_subdev *sd, struct v4l2_streamparm *param);                    /* Get parameters */INT (*s_parm) (struct V4l2_subdev *sd, struct v4l2_streamparm *param); /* Set parameters */INT (*enum_framesizes) (struct V4l2_subdev *sd, struct v4l2_frmsizeenum *fsize);      /* Enumerate frame sizes */int (*enum_frameintervals) (struct V4l2_subdev *sd, struct v4l2_frmivalenum *fival); /* Enumerate frame intervals */};
Registration and deregistration of 4.1 subdev

When we have implemented the V4l2_subdev that need to be implemented, we can call the following function to register the device with the V4L2 core layer:

int v4l2_device_register_subdev(struct v4l2_device*v4l2_dev, struct v4l2_subdev *sd)

When you unload a child device, you can call the following function to log off:

void v4l2_device_unregister_subdev(struct v4l2_subdev*sd)
5. Application layer specific process framework:

Let's use a picture to show it:

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.