欢迎您访问 最编程 本站为您分享编程语言代码,编程技术文章!
您现在的位置是: 首页

解析uvc设备的注册过程与uvc摄像头驱动相关

最编程 2024-08-13 20:12:16
...
static int uvc_probe(struct usb_interface *intf, const struct usb_device_id *id) { // 获取 USB 设备 struct usb_device *udev = interface_to_usbdev(intf); // 定义 UVC 设备 struct uvc_device *dev; int ret; // 如果 idVendor 和 idProduct 都存在,则打印已知 UVC 设备的信息 if (id->idVendor && id->idProduct) uvc_trace(UVC_TRACE_PROBE, "Probing known UVC device %s " "(%04x:%04x)\n", udev->devpath, id->idVendor, id->idProduct); // 否则打印通用 UVC 设备的信息 else uvc_trace(UVC_TRACE_PROBE, "Probing generic UVC device %s\n", udev->devpath); // 为设备分配内存并初始化 if ((dev = kzalloc(sizeof *dev, GFP_KERNEL)) == NULL) return -ENOMEM; // 初始化设备的各个链表 INIT_LIST_HEAD(&dev->entities); INIT_LIST_HEAD(&dev->chains); INIT_LIST_HEAD(&dev->streams); atomic_set(&dev->nstreams, 0); atomic_set(&dev->nmappings, 0); mutex_init(&dev->lock); // 获取 USB 设备 dev->udev = usb_get_dev(udev); dev->intf = usb_get_intf(intf); dev->intfnum = intf->cur_altsetting->desc.bInterfaceNumber; dev->quirks = (uvc_quirks_param == -1) ? id->driver_info : uvc_quirks_param; // 如果 USB 设备有产品名称,则使用该名称,否则使用默认名称 if (udev->product != NULL) strlcpy(dev->name, udev->product, sizeof dev->name); else snprintf(dev->name, sizeof dev->name, "UVC Camera (%04x:%04x)", le16_to_cpu(udev->descriptor.idVendor), le16_to_cpu(udev->descriptor.idProduct)); // 解析 Video Class 控制描述符 if (uvc_parse_control(dev) < 0) { uvc_trace(UVC_TRACE_PROBE, "Unable to parse UVC " "descriptors.\n"); goto error; } // 打印 UVC 设备信息 uvc_printk(KERN_INFO, "Found UVC %u.%02x device %s (%04x:%04x)\n", dev->uvc_version >> 8, dev->uvc_version & 0xff, udev->product ? udev->product : "<unnamed>", le16_to_cpu(udev->descriptor.idVendor), le16_to_cpu(udev->descriptor.idProduct)); if (dev->quirks != id->driver_info) { // 如果设备 quirks 不等于驱动程序信息,则打印信息 uvc_printk(KERN_INFO, "Forcing device quirks to 0x%x by module " "parameter for testing purpose.\n", dev->quirks); // 打印信息 uvc_printk(KERN_INFO, "Please report required quirks to the " "linux-uvc-devel mailing list.\n"); } /* Register the media and V4L2 devices. */ #ifdef CONFIG_MEDIA_CONTROLLER // 设置 media 设备的信息 dev->mdev.dev = &intf->dev; strlcpy(dev->mdev.model, dev->name, sizeof(dev->mdev.model)); if (udev->serial) strlcpy(dev->mdev.serial, udev->serial, sizeof(dev->mdev.serial)); strcpy(dev->mdev.bus_info, udev->devpath); dev->mdev.hw_revision = le16_to_cpu(udev->descriptor.bcdDevice); dev->mdev.driver_version = LINUX_VERSION_CODE; // 注册 media 设备 if (media_device_register(&dev->mdev) < 0) goto error; // 设置 v4l2 设备的信息 dev->vdev.mdev = &dev->mdev; #endif // 注册 v4l2 设备 if (v4l2_device_register(&intf->dev, &dev->vdev) < 0) goto error; /* Initialize controls. */ // 初始化控制器 if (uvc_ctrl_init_device(dev) < 0) goto error; /* Scan the device for video chains. */ // 扫描设备的视频链 if (uvc_scan_device(dev) < 0) goto error; /* Register video device nodes. */ // 注册视频设备节点 if (uvc_register_chains(dev) < 0) goto error; /* Save our data pointer in the interface data. */ // 在接口数据中保存数据指针 usb_set_intfdata(intf, dev); /* Initialize the interrupt URB. */ // 初始化中断 URB if ((ret = uvc_status_init(dev)) < 0) { uvc_printk(KERN_INFO, "Unable to initialize the status " "endpoint (%d), status interrupt will not be " "supported.\n", ret); } // 打印 UVC 设备初始化信息 uvc_trace(UVC_TRACE_PROBE, "UVC device initialized.\n"); // 启用 USB 自动挂起 usb_enable_autosuspend(udev); return 0; error: // 注销视频设备 uvc_unregister_video(dev); return -ENODEV; }

推荐阅读