Linux uvc摄像头驱动初探

时间:2022-07-27 19:02:01

本文基于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:
    ......   
  }
  ......
}