V4l2 basic framework of the following:
. 1 App: Read Write Open IOCtrl 2 ------------------------------------------ ------------------ 3 mainly provides a standard interface for the upper core layer call: . 4 V4L2-dev.c ---> . 5 static const struct the file_operations v4l2_fops = { . 6 .owner = THIS_MODULE, . 7 .read = v4l2_read, . 8 .write = v4l2_write, . 9 .Open = v4l2_open, 10 .get_unmapped_area = v4l2_get_unmapped_area, . 11 .mmap = v4l2_mmap, 12 .unlocked_ioctl = v4l2_ioctl, 13 #ifdef CONFIG_COMPAT 14 .compat_ioctl = v4l2_compat_ioctl32, 15 #endif 16 .release = v4l2_release, 17 .poll = v4l2_poll, 18 .llseek = no_llseek, 19 }; 20 21 22 23 ------------------------------------------------------------- 24 硬件相关: 25 |---v4l2_device_register --->重点 26 | 27 Uvc_driver.c ---|---uvc_register_chains 28 | uvc_register_terms 29 | uvc_register_video 30 | video_device_alloc --->重点 31 | video_register_device ---> 重点
The following case study analysis related to vivi.c call flow
vivi_init main processes:
. 1 vivi_init 2 vivi_create_instance . 3 v4l2_device_register ---> Register This structure: struct v4l2_device . 4 . 5 the dev-> Formats & FMT = [ 0 ]; set image format . 6 v4l2_ctrl_handler_init set properties . 7 the dev-> Volume = v4l2_ctrl_new_std (HDL, & vivi_ctrl_ops , . 8 V4L2_CID_AUDIO_VOLUME, 0 , 255 , . 1 , 200 is ); . 9 the dev-> Brightness = v4l2_ctrl_new_std (HDL, & vivi_ctrl_ops, 10 V4L2_CID_BRIGHTNESS, 0, 255, 1, 127); 11 dev->contrast = v4l2_ctrl_new_std(hdl, &vivi_ctrl_ops, 12 V4L2_CID_CONTRAST, 0, 255, 1, 16); 13 dev->saturation = v4l2_ctrl_new_std(hdl, &vivi_ctrl_ops, 14 V4L2_CID_SATURATION, 0, 255, 1, 127); 15 dev->hue = v4l2_ctrl_new_std(hdl, &vivi_ctrl_ops, 16 V4L2_CID_HUE, -128, 127, 1, 0); 17 dev->autogain = v4l2_ctrl_new_std(hdl, &vivi_ctrl_ops, 18 V4L2_CID_AUTOGAIN, 0, 1, 1, 1); 19 dev->gain = v4l2_ctrl_new_std(hdl, &vivi_ctrl_ops, 20 V4L2_CID_GAIN, 0, 255, 1, 100); 21 dev->button = v4l2_ctrl_new_custom(hdl, &vivi_ctrl_button, NULL); 22 dev->int32 = v4l2_ctrl_new_custom(hdl, &vivi_ctrl_int32, NULL); 23 dev->int64 = v4l2_ctrl_new_custom(hdl, &vivi_ctrl_int64, NULL); 24 dev->boolean = v4l2_ctrl_new_custom(hdl, &vivi_ctrl_boolean, NULL); 25 dev->menu = v4l2_ctrl_new_custom(hdl, &vivi_ctrl_menu, NULL); 26 dev->string = v4l2_ctrl_new_custom(hdl, &vivi_ctrl_string, NULL); 27 dev->bitmask = v4l2_ctrl_new_custom(hdl, &vivi_ctrl_bitmask, NULL); 28 29 vfd = video_device_alloc(); //主要是注册这个结构体;video_device 30 *vfd = vivi_template;// 31 vfd->v4l2_dev = &dev->v4l2_dev; 32 33 ret = video_register_device(vfd, VFL_TYPE_GRABBER, video_nr); 34 __video_register_device 35 vdev->cdev->ops = &v4l2_fops; 36 vdev->cdev->owner = owner; 37 ret = cdev_add(vdev->cdev, MKDEV(VIDEO_MAJOR, vdev->minor), 1); 38 if (ret < 0) { 39 the printk (KERN_ERR " % S: cdev_add failed \ n- " , __func__ in); 40 kfree (VDEV-> the cdev); 41 is VDEV-> the cdev = NULL; 42 is GOTO Cleanup; 43 is } 44 is 45 video_device [VDEV-> Minor] = VDEV ; // by associating the array 46 is 47 IF (VDEV-> v4l2_dev) { // before vivi.c provided with vfd-> v4l2_dev = & dev-> v4l2_dev ; interrelated 48 IF (VDEV-> v4l2_dev-> dev) 49 vdev->parent = vdev->v4l2_dev->dev; 50 if (vdev->ctrl_handler == NULL) 51 vdev->ctrl_handler = vdev->v4l2_dev->ctrl_handler; 52 /* If the prio state pointer is NULL, then use the v4l2_device 53 prio state. */ 54 if (vdev->prio == NULL) 55 } 56 57 58 static const struct v4l2_file_operations vivi_fops = { 59 .owner = THIS_MODULE, 60 .open = v4l2_fh_open, 61 .release = vivi_close, 62 .read = vivi_read, 63 .poll = vivi_poll, 64 .unlocked_ioctl = video_ioctl2, /* V4L2 ioctl handler */ 65 .mmap = vivi_mmap, 66 }; 67 68 69 static struct video_device vivi_template = { 70 .name = "vivi", 71 .fops = &vivi_fops, 72 .ioctl_ops = &vivi_ioctl_ops, 73 .release = video_device_release, 74 75 .tvnorms = V4L2_STD_525_60, 76 .current_norm = V4L2_STD_NTSC_M, 77 };
open process:
. 1 Open flow: 2 App: Open ( " / dev / video0 " , ....) . 3 --------------------------- ----- . 4 Open: . 5 v4l2_fops.open . 6 VDEV = video_devdata (the filp); . 7 video_device [iminor (File-> f_path.dentry-> d_inode)] // __video_register_device the structure vivi.v registered on video_device the memory array 8 VDEV-> fops-> Open transferred fops vivi.c set, the key here is very exciting, we understand about 9 vivi_template 10 v4l2_fh_open
read process:
. 1 Read Process: 2 v4l2_fops.read . 3 struct video_device VDEV * = video_devdata (the filp); . 4 VDEV-> fops-> Read
ioctrl process:
. 1 App: ioctl can be set by obtaining luminance information, and the driver who receives the management information 2 v4l2_ctrl information set . 3 v4l2_ctrl_handler to manage . 4 . 5 ioctl process: . 6 v4l2_fops.v4l2_ioctl . 7 struct video_device VDEV * = video_devdata ( the filp); . 8 VDEV-> fops-> unlocked_ioctl (the filp, cmd, Arg); . 9 vivi_fops.video_ioctl2 10 video_usercopy (File, cmd, Arg, __video_do_ioctl); // pass a callback function into __video_do_ioctl . 11 struct video_device * = VFD video_devdata (File); 12 //The APP incoming cmd obtained, set "certain property" 13 is Switch (cmd) { 14 15 } 16 . 17 18 is or through the v4l2_ctrl . 19 for ctrl_handler related setup code 20 is vivi_create_instance 21 is v4l2_ctrl_handler_init (HDL, . 11 ); 22 is v4l2_ctrl_new_std (HDL, & vivi_ctrl_ops, V4L2_CID_AUDIO_VOLUME, 0 , 255 , . 1 , 200 is );
... 23 is the dev-> = v4l2_dev.ctrl_handler HDL; associated with the VDEV 24 video_register_device 25 __video_register_device 26 is IF (VDEV-> ctrl_handler == NULL) 27 VDEV-> = VDEV-ctrl_handler> v4l2_dev-> ctrl_handler; 28 29 __video_do_ioctl 30 Case VIDIOC_QUERYCTRL: 31 is IF (VFH && vfh-> ctrl_handler) 32 RET = v4l2_queryctrl (vfh- > ctrl_handler, P); 33 is REF = find_ref (HDL, ID); // then find the corresponding v4l2_ctrl based on ID, the corresponding structure is then further found to fill