📄 usbvision-video.c
字号:
{ .fops = &usbvision_vbi_fops, .release = video_device_release, .name = "usbvision-vbi", .minor = -1,};static struct video_device *usbvision_vdev_init(struct usb_usbvision *usbvision, struct video_device *vdev_template, char *name){ struct usb_device *usb_dev = usbvision->dev; struct video_device *vdev; if (usb_dev == NULL) { err("%s: usbvision->dev is not set", __func__); return NULL; } vdev = video_device_alloc(); if (NULL == vdev) { return NULL; } *vdev = *vdev_template;// vdev->minor = -1; vdev->parent = &usb_dev->dev; snprintf(vdev->name, sizeof(vdev->name), "%s", name); video_set_drvdata(vdev, usbvision); return vdev;}// unregister video4linux devicesstatic void usbvision_unregister_video(struct usb_usbvision *usbvision){ // vbi Device: if (usbvision->vbi) { PDEBUG(DBG_PROBE, "unregister /dev/vbi%d [v4l2]", usbvision->vbi->num); if (usbvision->vbi->minor != -1) { video_unregister_device(usbvision->vbi); } else { video_device_release(usbvision->vbi); } usbvision->vbi = NULL; } // Radio Device: if (usbvision->rdev) { PDEBUG(DBG_PROBE, "unregister /dev/radio%d [v4l2]", usbvision->rdev->num); if (usbvision->rdev->minor != -1) { video_unregister_device(usbvision->rdev); } else { video_device_release(usbvision->rdev); } usbvision->rdev = NULL; } // Video Device: if (usbvision->vdev) { PDEBUG(DBG_PROBE, "unregister /dev/video%d [v4l2]", usbvision->vdev->num); if (usbvision->vdev->minor != -1) { video_unregister_device(usbvision->vdev); } else { video_device_release(usbvision->vdev); } usbvision->vdev = NULL; }}// register video4linux devicesstatic int __devinit usbvision_register_video(struct usb_usbvision *usbvision){ // Video Device: usbvision->vdev = usbvision_vdev_init(usbvision, &usbvision_video_template, "USBVision Video"); if (usbvision->vdev == NULL) { goto err_exit; } if (video_register_device(usbvision->vdev, VFL_TYPE_GRABBER, video_nr)<0) { goto err_exit; } printk(KERN_INFO "USBVision[%d]: registered USBVision Video device /dev/video%d [v4l2]\n", usbvision->nr, usbvision->vdev->num); // Radio Device: if (usbvision_device_data[usbvision->DevModel].Radio) { // usbvision has radio usbvision->rdev = usbvision_vdev_init(usbvision, &usbvision_radio_template, "USBVision Radio"); if (usbvision->rdev == NULL) { goto err_exit; } if (video_register_device(usbvision->rdev, VFL_TYPE_RADIO, radio_nr)<0) { goto err_exit; } printk(KERN_INFO "USBVision[%d]: registered USBVision Radio device /dev/radio%d [v4l2]\n", usbvision->nr, usbvision->rdev->num); } // vbi Device: if (usbvision_device_data[usbvision->DevModel].vbi) { usbvision->vbi = usbvision_vdev_init(usbvision, &usbvision_vbi_template, "USBVision VBI"); if (usbvision->vdev == NULL) { goto err_exit; } if (video_register_device(usbvision->vbi, VFL_TYPE_VBI, vbi_nr)<0) { goto err_exit; } printk(KERN_INFO "USBVision[%d]: registered USBVision VBI device /dev/vbi%d [v4l2] (Not Working Yet!)\n", usbvision->nr, usbvision->vbi->num); } // all done return 0; err_exit: err("USBVision[%d]: video_register_device() failed", usbvision->nr); usbvision_unregister_video(usbvision); return -1;}/* * usbvision_alloc() * * This code allocates the struct usb_usbvision. * It is filled with default values. * * Returns NULL on error, a pointer to usb_usbvision else. * */static struct usb_usbvision *usbvision_alloc(struct usb_device *dev){ struct usb_usbvision *usbvision; if ((usbvision = kzalloc(sizeof(struct usb_usbvision), GFP_KERNEL)) == NULL) { goto err_exit; } usbvision->dev = dev; mutex_init(&usbvision->lock); /* available */ // prepare control urb for control messages during interrupts usbvision->ctrlUrb = usb_alloc_urb(USBVISION_URB_FRAMES, GFP_KERNEL); if (usbvision->ctrlUrb == NULL) { goto err_exit; } init_waitqueue_head(&usbvision->ctrlUrb_wq); usbvision_init_powerOffTimer(usbvision); return usbvision;err_exit: if (usbvision && usbvision->ctrlUrb) { usb_free_urb(usbvision->ctrlUrb); } if (usbvision) { kfree(usbvision); } return NULL;}/* * usbvision_release() * * This code does final release of struct usb_usbvision. This happens * after the device is disconnected -and- all clients closed their files. * */static void usbvision_release(struct usb_usbvision *usbvision){ PDEBUG(DBG_PROBE, ""); mutex_lock(&usbvision->lock); usbvision_reset_powerOffTimer(usbvision); usbvision->initialized = 0; mutex_unlock(&usbvision->lock); usbvision_remove_sysfs(usbvision->vdev); usbvision_unregister_video(usbvision); if (usbvision->ctrlUrb) { usb_free_urb(usbvision->ctrlUrb); } kfree(usbvision); PDEBUG(DBG_PROBE, "success");}/*********************** usb interface **********************************/static void usbvision_configure_video(struct usb_usbvision *usbvision){ int model; if (usbvision == NULL) return; model = usbvision->DevModel; usbvision->palette = usbvision_v4l2_format[2]; // V4L2_PIX_FMT_RGB24; if (usbvision_device_data[usbvision->DevModel].Vin_Reg2_override) { usbvision->Vin_Reg2_Preset = usbvision_device_data[usbvision->DevModel].Vin_Reg2; } else { usbvision->Vin_Reg2_Preset = 0; } usbvision->tvnormId = usbvision_device_data[model].VideoNorm; usbvision->video_inputs = usbvision_device_data[model].VideoChannels; usbvision->ctl_input = 0; /* This should be here to make i2c clients to be able to register */ /* first switch off audio */ usbvision_audio_off(usbvision); if (!PowerOnAtOpen) { /* and then power up the noisy tuner */ usbvision_power_on(usbvision); usbvision_i2c_register(usbvision); }}/* * usbvision_probe() * * This procedure queries device descriptor and accepts the interface * if it looks like USBVISION video device * */static int __devinit usbvision_probe(struct usb_interface *intf, const struct usb_device_id *devid){ struct usb_device *dev = usb_get_dev(interface_to_usbdev(intf)); struct usb_interface *uif; __u8 ifnum = intf->altsetting->desc.bInterfaceNumber; const struct usb_host_interface *interface; struct usb_usbvision *usbvision = NULL; const struct usb_endpoint_descriptor *endpoint; int model,i; PDEBUG(DBG_PROBE, "VID=%#04x, PID=%#04x, ifnum=%u", dev->descriptor.idVendor, dev->descriptor.idProduct, ifnum); model = devid->driver_info; if ( (model<0) || (model>=usbvision_device_data_size) ) { PDEBUG(DBG_PROBE, "model out of bounds %d",model); return -ENODEV; } printk(KERN_INFO "%s: %s found\n", __func__, usbvision_device_data[model].ModelString); if (usbvision_device_data[model].Interface >= 0) { interface = &dev->actconfig->interface[usbvision_device_data[model].Interface]->altsetting[0]; } else { interface = &dev->actconfig->interface[ifnum]->altsetting[0]; } endpoint = &interface->endpoint[1].desc; if ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) != USB_ENDPOINT_XFER_ISOC) { err("%s: interface %d. has non-ISO endpoint!", __func__, ifnum); err("%s: Endpoint attributes %d", __func__, endpoint->bmAttributes); return -ENODEV; } if ((endpoint->bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_OUT) { err("%s: interface %d. has ISO OUT endpoint!", __func__, ifnum); return -ENODEV; } if ((usbvision = usbvision_alloc(dev)) == NULL) { err("%s: couldn't allocate USBVision struct", __func__); return -ENOMEM; } if (dev->descriptor.bNumConfigurations > 1) { usbvision->bridgeType = BRIDGE_NT1004; } else if (model == DAZZLE_DVC_90_REV_1_SECAM) { usbvision->bridgeType = BRIDGE_NT1005; } else { usbvision->bridgeType = BRIDGE_NT1003; } PDEBUG(DBG_PROBE, "bridgeType %d", usbvision->bridgeType); mutex_lock(&usbvision->lock); /* compute alternate max packet sizes */ uif = dev->actconfig->interface[0]; usbvision->num_alt=uif->num_altsetting; PDEBUG(DBG_PROBE, "Alternate settings: %i",usbvision->num_alt); usbvision->alt_max_pkt_size = kmalloc(32* usbvision->num_alt,GFP_KERNEL); if (usbvision->alt_max_pkt_size == NULL) { err("usbvision: out of memory!\n"); mutex_unlock(&usbvision->lock); return -ENOMEM; } for (i = 0; i < usbvision->num_alt ; i++) { u16 tmp = le16_to_cpu(uif->altsetting[i].endpoint[1].desc. wMaxPacketSize); usbvision->alt_max_pkt_size[i] = (tmp & 0x07ff) * (((tmp & 0x1800) >> 11) + 1); PDEBUG(DBG_PROBE, "Alternate setting %i, max size= %i",i, usbvision->alt_max_pkt_size[i]); } usbvision->nr = usbvision_nr++; usbvision->have_tuner = usbvision_device_data[model].Tuner; if (usbvision->have_tuner) { usbvision->tuner_type = usbvision_device_data[model].TunerType; } usbvision->tuner_addr = ADDR_UNSET; usbvision->DevModel = model; usbvision->remove_pending = 0; usbvision->iface = ifnum; usbvision->ifaceAlt = 0; usbvision->video_endp = endpoint->bEndpointAddress; usbvision->isocPacketSize = 0; usbvision->usb_bandwidth = 0; usbvision->user = 0; usbvision->streaming = Stream_Off; usbvision_register_video(usbvision); usbvision_configure_video(usbvision); mutex_unlock(&usbvision->lock); usb_set_intfdata (intf, usbvision); usbvision_create_sysfs(usbvision->vdev); PDEBUG(DBG_PROBE, "success"); return 0;}/* * usbvision_disconnect() * * This procedure stops all driver activity, deallocates interface-private * structure (pointed by 'ptr') and after that driver should be removable * with no ill consequences. * */static void __devexit usbvision_disconnect(struct usb_interface *intf){ struct usb_usbvision *usbvision = usb_get_intfdata(intf); PDEBUG(DBG_PROBE, ""); if (usbvision == NULL) { err("%s: usb_get_intfdata() failed", __func__); return; } usb_set_intfdata (intf, NULL); mutex_lock(&usbvision->lock); // At this time we ask to cancel outstanding URBs usbvision_stop_isoc(usbvision); if (usbvision->power) { usbvision_i2c_unregister(usbvision); usbvision_power_off(usbvision); } usbvision->remove_pending = 1; // Now all ISO data will be ignored usb_put_dev(usbvision->dev); usbvision->dev = NULL; // USB device is no more mutex_unlock(&usbvision->lock); if (usbvision->user) { printk(KERN_INFO "%s: In use, disconnect pending\n", __func__); wake_up_interruptible(&usbvision->wait_frame); wake_up_interruptible(&usbvision->wait_stream); } else { usbvision_release(usbvision); } PDEBUG(DBG_PROBE, "success");}static struct usb_driver usbvision_driver = { .name = "usbvision", .id_table = usbvision_table, .probe = usbvision_probe, .disconnect = usbvision_disconnect};/* * usbvision_init() * * This code is run to initialize the driver. * */static int __init usbvision_init(void){ int errCode; PDEBUG(DBG_PROBE, ""); PDEBUG(DBG_IO, "IO debugging is enabled [video]"); PDEBUG(DBG_PROBE, "PROBE debugging is enabled [video]"); PDEBUG(DBG_MMAP, "MMAP debugging is enabled [video]"); /* disable planar mode support unless compression enabled */ if (isocMode != ISOC_MODE_COMPRESS ) { // FIXME : not the right way to set supported flag usbvision_v4l2_format[6].supported = 0; // V4L2_PIX_FMT_YVU420 usbvision_v4l2_format[7].supported = 0; // V4L2_PIX_FMT_YUV422P } errCode = usb_register(&usbvision_driver); if (errCode == 0) { printk(KERN_INFO DRIVER_DESC " : " USBVISION_VERSION_STRING "\n"); PDEBUG(DBG_PROBE, "success"); } return errCode;}static void __exit usbvision_exit(void){ PDEBUG(DBG_PROBE, ""); usb_deregister(&usbvision_driver); PDEBUG(DBG_PROBE, "success");}module_init(usbvision_init);module_exit(usbvision_exit);/* * Overrides for Emacs so that we follow Linus's tabbing style. * --------------------------------------------------------------------------- * Local variables: * c-basic-offset: 8 * End: */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -