上一篇文章中,已經介紹了v4l2_open、v4l2_read、v4l2_write的調用過程,相對於v4l2_ioctl,它們是比較簡單的。下面來分析v4l2_ioctl。注意在這里還是分析以vivi.c為例,進行分析。
app: ioctl
---------------------------------------------------------------------------
drv: v4L2_fops.unlocked_ioctl
.v4L2_ioctl
vdev = video_devdata(filp);
vdev->fops->unlocked_ioctl(filp, cmd, arg);//調用具體設備提供的unlocked_ioctl,因為本篇文章是以vivi.c為例進行分析,.unlocked_ioctl = video_ioctl2
video_ioctl2
video_usercopy(file, cmd, arg, __video_do_ioctl)
__video_do_ioctl
video_ioctl2
long video_ioctl2(struct file *file,unsigned int cmd, unsigned long arg)
{
//根據命令cmd的不同,調用__video_do_ioctl,將數據拷貝到內核空間
return video_usercopy(file, cmd, arg, __video_do_ioctl);
}
__video_do_ioctl
//以次設備號為下標,從video_device[]中取出對應的video_device,此處就是vivi_template
struct video_device *vfd = video_devdata(file);
//獲取vivi_template的ioctl_ops
const struct v4l2_ioctl_ops *ops = vfd->ioctl_ops;
----------
switch (cmd) {
/* --- capabilities ------------------------------------------ */
case VIDIOC_QUERYCAP://cmd命令
{
//v4l2設備的能力結構體
struct v4l2_capability *cap = (struct v4l2_capability *)arg;
if (!ops->vidioc_querycap)
break;
cap->version = LINUX_VERSION_CODE;
//根據不同的cmd,調用到了ioctl_ops中的vidioc_querycap
ret = ops->vidioc_querycap(file, fh, cap);
----
break
}
現總結一下這個過程:
1、video_device被設置成了vivi_template //在函數vivi_create_instance中被設置
2、vdev->cdev->ops = &v4l2_fops; //在函數__video_register_device中被設置
3、video_device[vdev->minor] = vdev;//在函數__video_register_device中被設置
當用戶空間調用ioctl的時候,v4l2_fops的v4l2_ioctl將被調用;
在v4l2_ioctl中,vivi_template->fops->unlocked_ioctl(filp, cmd, arg) 即video_ioctl2函數會被調用;
在video_ioctl2中,__video_do_ioctl函數會被調用;
在__video_do_ioctl中,根據cmd來調用vivi_template中的vivi_ioctl_ops結構體中對應的函數。