A video transmission mode: In IIC protocol, through the IO port transport stream:
Video transmission way: usb interface to transmit the video stream:
Drivers: character device drivers
How to write drivers: construction file_operations
To tell the kernel
Entry function
Export function
v4l2 drive frame: the core layer -> file_operations
Hardware-related layers:
1, the camera device into the usb on pc with a virtual machine, dmesg prints found some usb camera equipment information, grep to find specific location information printed in the kernel;
2, look for the print information
3, open the file with source insight uvc_driver.c or other reading software
3.1 -->struct uvc_driver
--> uvc_probe:
v4l2_device_register
uvc_register_chains ---uvc_register_video--video_device video_register_device
---struct video_device *vdev;
struct uvc_device *dev,
vdev->v4l2_dev = &dev->vdev;
vdev->fops = &uvc_fops;
media_device_register
4, there v4l2-framework.txt document may refer to the kernel
5, can analyze the virtual camera driver: vivi.c
vivi_init-->vivi_create_instance-->video_device_alloc-->video_register_device-->__video_register_device-->vdev->cdev = cdev_alloc();--> cdev_add()
6, in the kernel already provides some basic functions file_operations v4l2_fops, so we do not need to write character device functions. When the application layer calls the ioctl function, the call file_operations ioctl ---. Unlocked_ioctl = v4l2_ioctl,
v4l2_ioctl------
if (video_is_registered(vdev))
ret = vdev->fops->unlocked_ioctl(filp, cmd, arg);
If video_device already registered, call video_device inside fops function inside unlocked_ioctl function.
The unlocked_ioctl function in the kernel has been written, we do not need to write --- video_usercopy
----cmd_input_size(cmd);
----check_array_args(cmd, parg, &array_size, &user_ptr, &kernel_ptr);
---- get what we want
static unsigned long cmd_input_size(unsigned int cmd) { /* Size of structure up to and including 'field' */ #define CMDINSIZE(cmd, type, field) \ case VIDIOC_##cmd: \ return offsetof(struct v4l2_##type, field) + \ sizeof(((struct v4l2_##type *)0)->field); switch (cmd) { CMDINSIZE(ENUM_FMT, fmtdesc, type); CMDINSIZE(G_FMT, format, type); CMDINSIZE(QUERYBUF, buffer, length); CMDINSIZE(G_PARM, streamparm, type); CMDINSIZE(ENUMSTD, standard, index); CMDINSIZE(ENUMINPUT, input, index); CMDINSIZE(G_CTRL, control, id); CMDINSIZE(G_TUNER, tuner, index); CMDINSIZE(QUERYCTRL, queryctrl, id); CMDINSIZE(QUERYMENU, querymenu, index); CMDINSIZE(ENUMOUTPUT, output, index); CMDINSIZE(G_MODULATOR, modulator, index); CMDINSIZE(G_FREQUENCY, frequency, tuner); CMDINSIZE(CROPCAP, cropcap, type); CMDINSIZE(G_CROP, crop, type); CMDINSIZE(ENUMAUDIO, audio, index); CMDINSIZE(ENUMAUDOUT, audioout, index); CMDINSIZE(ENCODER_CMD, encoder_cmd, flags); CMDINSIZE(TRY_ENCODER_CMD, encoder_cmd, flags); CMDINSIZE(G_SLICED_VBI_CAP, sliced_vbi_cap, type); CMDINSIZE(ENUM_FRAMESIZES, frmsizeenum, pixel_format); CMDINSIZE(ENUM_FRAMEINTERVALS, frmivalenum, height); default: return _IOC_SIZE(cmd); } }
with
static int check_array_args(unsigned int cmd, void *parg, size_t *array_size, void * __user *user_ptr, void ***kernel_ptr) { int ret = 0; switch (cmd) { case VIDIOC_QUERYBUF: case VIDIOC_QBUF: case VIDIOC_DQBUF: { struct v4l2_buffer *buf = parg; if (V4L2_TYPE_IS_MULTIPLANAR(buf->type) && buf->length > 0) { if (buf->length > VIDEO_MAX_PLANES) { ret = -EINVAL; break; } *user_ptr = (void __user *)buf->m.planes; *kernel_ptr = (void *)&buf->m.planes; *array_size = sizeof(struct v4l2_plane) * buf->length; ret = 1; } break; } case VIDIOC_S_EXT_CTRLS: case VIDIOC_G_EXT_CTRLS: case VIDIOC_TRY_EXT_CTRLS: { struct v4l2_ext_controls *ctrls = parg; if (ctrls->count != 0) { if (ctrls->count > V4L2_CID_MAX_CTRLS) { ret = -EINVAL; break; } *user_ptr = (void __user *)ctrls->controls; *kernel_ptr = (void *)&ctrls->controls; *array_size = sizeof(struct v4l2_ext_control) * ctrls->count; ret = 1; } break; } } Return right; }
7, strace can be obtained by calling the system during program execution
strace -o xawtv.log xawtv
xawtv involved in the system call will be recorded in xawtv.log