本文基于AM6C平台Linux3.0.8内核。
1.drivers/media/video/uvc/Makefile
uvcvideo-objs := uvc_driver.o uvc_queue.o uvc_v4l2.o uvc_video.o uvc_ctrl.o \ uvc_status.o uvc_isight.o obj-$(CONFIG_USB_VIDEO_CLASS) += uvcvideo.o
2.drivers/media/video/uvc/uvc_driver.c
module_init(uvc_init); static int __init uvc_init(void){ ...... result = usb_register(&uvc_driver.driver); ...... } struct uvc_driver uvc_driver = { .driver = { .name = "uvcvideo", .probe = uvc_probe, .disconnect = uvc_disconnect, .suspend = uvc_suspend, .resume = uvc_resume, .reset_resume = uvc_reset_resume, .id_table = uvc_ids, .supports_autosuspend = 1, }, }; static int uvc_probe(struct usb_interface *intf,const struct usb_device_id *id){ ...... uvc_register_chains(dev); ...... } static int uvc_register_chains(struct uvc_device *dev){ ...... ret = uvc_register_terms(dev, chain); ...... } static int uvc_register_terms(struct uvc_device *dev,struct uvc_video_chain *chain){ ...... ret = uvc_register_video(dev, stream); ...... } static int uvc_register_video(struct uvc_device *dev,struct uvc_streaming *stream){ ...... vdev = video_device_alloc(); ...... vdev->v4l2_dev = &dev->vdev; vdev->fops = &uvc_fops; vdev->release = uvc_release; ...... ret = video_register_device(vdev, VFL_TYPE_GRABBER, -1); ...... }
3.drivers/media/video/uvc/uvc_v4l2.c
const struct v4l2_file_operations uvc_fops = { .owner = THIS_MODULE, .open = uvc_v4l2_open, .release = uvc_v4l2_release, .unlocked_ioctl = uvc_v4l2_ioctl, .read = uvc_v4l2_read, .mmap = uvc_v4l2_mmap, .poll = uvc_v4l2_poll, #ifndef CONFIG_MMU .get_unmapped_area = uvc_v4l2_get_unmapped_area, #endif }; static long uvc_v4l2_ioctl(struct file *file,unsigned int cmd, unsigned long arg){ ...... return video_usercopy(file, cmd, arg, uvc_v4l2_do_ioctl); } static long uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg){ ...... switch (cmd) { case VIDIOC_QUERYCAP:...... case VIDIOC_QUERYCTRL: case VIDIOC_G_CTRL: case VIDIOC_S_CTRL: case VIDIOC_QUERYMENU: case VIDIOC_G_EXT_CTRLS: case VIDIOC_S_EXT_CTRLS: case VIDIOC_TRY_EXT_CTRLS: case VIDIOC_ENUMINPUT: case VIDIOC_G_INPUT: case VIDIOC_S_INPUT: case VIDIOC_ENUM_FMT: case VIDIOC_TRY_FMT: case VIDIOC_S_FMT: case VIDIOC_G_FMT: case VIDIOC_ENUM_FRAMESIZES: case VIDIOC_ENUM_FRAMEINTERVALS: case VIDIOC_G_PARM: case VIDIOC_S_PARM: case VIDIOC_CROPCAP: case VIDIOC_G_CROP: case VIDIOC_S_CROP: case VIDIOC_REQBUFS: case VIDIOC_QUERYBUF: case VIDIOC_QBUF: case VIDIOC_DQBUF: case VIDIOC_STREAMON: case VIDIOC_STREAMOFF: case VIDIOC_ENUMSTD: case VIDIOC_QUERYSTD: case VIDIOC_G_STD: case VIDIOC_S_STD: case VIDIOC_OVERLAY: case VIDIOC_ENUMAUDIO: case VIDIOC_ENUMAUDOUT: case VIDIOC_ENUMOUTPUT: case __UVCIOC_CTRL_ADD: case __UVCIOC_CTRL_MAP_OLD: case __UVCIOC_CTRL_MAP: case UVCIOC_CTRL_MAP: case __UVCIOC_CTRL_GET: case __UVCIOC_CTRL_SET: case UVCIOC_CTRL_QUERY: ...... } ...... }