Write a v4l2 virtual driver _ 1 and v4l2 virtual _ 1
Introduction
Because both qcom and linux use the v4l2 framework as the drive framework of camera, the following documents are recorded based on the learning notes. This document is a personal study note for "teacher Wei Dongshan video tutorial Phase 3". Thank you very much for your information. This record is only for learning and communication. If your interest is violated, please contact the blogger to delete it.
Register video_device
Code demo
The first is the entry, exit, and license of the driver, and then the first step is to allocate, set and register a video_device structure (based on the kernel version: linux-3.13.1 ).
# Include <linux/module. h> # include <linux/delay. h> # include <linux/errno. h> # include <linux/fs. h> # include <linux/kernel. h> # include <linux/slab. h> # include <linux/mm. h> # include <linux/ioport. h> # include <linux/init. h> # include <linux/sched. h> # include <linux/pci. h> # include <linux/random. h> # include <linux/version. h> # include <linux/mutex. h> # include <linux/videodev2.h> # include <linux/dma-mapping.h> # include <linux/interrupt. h> # include <linux/kthread. h> # include <linux/highmem. h> # include <linux/freezer. h> # include <media/videobuf-vmalloc.h> # include <media/v4l2-device.h> # include <media/v4l2-ioctl.h> # define DRIVER_NAME "myvivi_video" static struct video_device * myvivi_device; struct v4l2_devicemyvivi_v4l2_dev; static void myvivi_release (struct video_device * vdev) {} static const struct v4l2_file_operations myvivi_fops = {. owner = THIS_MODULE,}; static int myvivi_init (void) {int error;/* 1. assign a video_device struct */myvivi_device = video_device_alloc ();/* 2. set */strlcpy (kernel, DRIVER_NAME, sizeof (kernel); error = v4l2_device_register (NULL, & register); myvivi_device-> v4l2_dev = & Consumer; myvivi_device-> release = myvivi_release; myvivi_device-> fops = & myvivi_fops;/* 2.1 */error = video_register_device (myvivi_device, VFL_TYPE_GRABBER,-1); return error;} static void myvivi_exit (void) {video_unregister_device (myvivi_device); video_device_release (myvivi_device);} module_init (myvivi_init); module_exit (myvivi_exit); MODULE_LICENSE ("GPL ");
Code Description
First, assign a video_device_alloc to allocate a v4l2_device structure, then fill in the v4l2_dev parameter set for this structure, the operation function fops, And the release function release. In the code, for simplicity, all fops and release functions are set to empty functions. Register the v4l2 device. Note the video_register_device function. The first parameter indicates the video_device structure to be registered. The VFL_TYPE_GRABBER parameter indicates the image collection device and the last-1 parameter, the first idle device name is used during registration. If/dev/video0 has been used, the registration will be used as/dev/video1. if the parameter is not-1, for example, 5, then the registered device file is/dev/video5. the last is the driver exit. The corresponding operation is to cancel the previously registered v4l2 device and then destroy the device structure. In this way, a simple v4l2 device is complete.
Note:
The kernel version I used is the linux-3.13.1, in which the registration can be successful only after the v4l2_dev parameter, fops operation function, and release function release are filled with the v4l2_device structure, otherwise, the driver reports errors such as null pointers or parameters. At the same time, before loading the driver, ensure that the v4l2 driver module on which the kernel depends has been loaded. v4l2 generally has the following modules: videodev. ko videobuf-vmalloc.ko videobuf-core.ko v4l2-common.ko driver depends on which modules can use sudo modinfo myvivi. ko.
Effect demonstration
After insmod loads the driver module, a video * Device node is generated. The effect is as follows:
Next, install the tool: sudo apt-get install xawtv. After using the tool, you will be prompted:
Failed to query video capabilities: Inappropriate ioctl for devicelibv4l2: error getting capabilities: Inappropriate ioctl for deviceFailed to query video capabilities: Inappropriate ioctl for devicelibv4l2: error getting capabilities: Inappropriate ioctl for devicevid-open-auto: failed to open a capture device at /dev/video0vid-open: could not find a suitable videodevno video grabber device available
Indicates a video device.
When xawtv was used earlier, it was prompted that no suitable video device was found, so this step is to mark the previously written v4l2 registration driver as a video device.
Code Description
Add the following code:
............... Static const struct v4l2_file_operations myvivi_fops = {. owner = THIS_MODULE ,. ioctl = video_ioctl2,/* V4L2 ioctl handler */}; static int myvivi_vidioc_querycap (struct file * file, void * priv, struct v4l2_capability * cap) {strcpy (cap-> driver, "myvivi"); strcpy (cap-> card, "myvivi"); cap-> version = 0x0001; cap-> capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING; /* Indicates a video capturing device and accessing */return 0 through ioctl;} static const struct v4l2_ioctl_ops myvivi_ioctl_ops = {// indicates that it is a camera device. vidioc_querycap = myvivi_vidioc_querycap,}; static int myvivi_init (void) {int error;/* 1. assign a video_device struct */myvivi_device = video_device_alloc ();/* 2. set */strlcpy (kernel, DRIVER_NAME, sizeof (kernel); error = v4l2_device_register (NULL, & register); myvivi_device-> v4l2_dev = & Consumer; myvivi_device-> release = myvivi_release; myvivi_device-> fops = & myvivi_fops; myvivi_device-> ioctl_ops = & myvivi_ioctl_ops ;..............}..............
A newly added myvivi_ioctl_ops operation function structure is initialized, And the myvivi_vidioc_querycap function is filled in. In the application, this function is called to determine the driver type. In this function, V4L2_CAP_VIDEO_CAPTURE indicates that the driver is a video retrieval device, and V4L2_CAP_STREAMING indicates that data is obtained through ioctl. At the same time, when calling the myvivi_vidioc_querycap function, you also need to call the ioctl function in myvivi_fops, so you also need to fill in the ioctl. Here we use the standard ioctl operation function video_ioctl2 provided by v4l2.
Effect demonstration
Then we continue to use the xawtv tool to test the driver. The effect is as follows:
It indicates that xawtv finds/dev/video0 as a video device.
Set the supported video format
In the previous step, xawtv has identified that the driver of the device is a video device, and then sets the video format supported by the driver in the driver.
Code Description
Static struct v4l2_format myvivi_format;/* lists the supported formats */static int myvivi_vidioc_enum_fmt_vid_cap (struct file * file, void * priv, struct v4l2_fmtdesc * f) {if (f-> index> = 1)/* only one format is supported. Therefore, if f-> index is set to be greater than or equal to 1, an error is returned */return-EINVAL; strcpy (f-> description, ", packed, YUYV"); f-> pixelformat = V4L2_PIX_FMT_YUYV; return 0 ;} /* return the current format */static int myvivi_vidioc_g_fmt_vid_cap (struct file * file, void * Priv, struct v4l2_format * f) {memcpy (f, & myvivi_format, sizeof (myvivi_format); return (0 );} /* test whether the driver supports a certain format */static int myvivi_vidioc_try_fmt_vid_cap (struct file * file, void * priv, struct v4l2_format * f) {unsigned int maxw, maxh; if (f-> fmt. pix. pixelformat! = V4L2_PIX_FMT_YUYV) return-EINVAL;/* maximum width and height supported by the device */maxw = 1024; maxh = 768;/* adjust the maximum and minimum width, height, and alignment mode * calculate bytesperline, sizeimage */v4l_bound_align_image (& f-> fmt. pix. width, 48, maxw, 2, & f-> fmt. pix. height, 32, maxh, 0, 0); f-> fmt. pix. bytesperline = (f-> fmt. pix. width * 16)> 3;/* set the color depth to 16 */f-> fmt. pix. sizeimage = f-> fmt. pix. height * f-> fmt. pix. bytesperline;/* set image size */return 0;} static int myvivi_vidioc_s_fmt_vid_cap (struct file * file, void * priv, struct v4l2_format * f) {int ret = partition (file, NULL, f); if (ret <0) return ret; memcpy (& myvivi_format, f, sizeof (myvivi_format); return ret ;} static const struct v4l2_ioctl_ops myvivi_ioctl_ops = {// indicates that it is a camera device. vidioc_querycap = myvivi_vidioc_querycap,/* used to list, obtain, test, and set the format of camera data */. vidioc_enum_fmt_vid_cap = myvivi_vidioc_enum_fmt_vid_cap ,. vidioc_g_fmt_vid_cap = myvivi_vidioc_g_fmt_vid_cap ,. vidioc_try_fmt_vid_cap = myvivi_vidioc_try_fmt_vid_cap ,. vidioc_s_fmt_vid_cap = myvivi_vidioc_s_fmt_vid_cap ,};
As shown above, a total of four functions are added. Myvivi_vidioc_enum_fmt_vid_cap: used to set the supported formats. Here, only one format is supported: V4L2_PIX_FMT_YUYV. Myvivi_vidioc_g_fmt_vid_cap: used to obtain supported video format information. The format information is saved in the myvivi_format structure. Myvivi_vidioc_try_fmt_vid_cap: used to test whether a received video format is supported by the driver of the device. information such as width, height, and image size of the video in this format is set. Myvivi_vidioc_s_fmt_vid_cap: first, use myvivi_vidioc_try_fmt_vid_cap to determine whether the input format is supported. If yes, it is saved to the myvivi_format structure.
Effect demonstration
Xawtv is also used to demonstrate the effect, but it is not obvious here.
We can see that xawtv has read some format-related information.