⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 em28xx-video.c

📁 trident tm5600的linux驱动
💻 C
📖 第 1 页 / 共 4 页
字号:
	rc = videobuf_mmap_mapper(&fh->vb_vidq, vma);	em28xx_videodbg("vma start=0x%08lx, size=%ld, ret=%d\n",		(unsigned long)vma->vm_start,		(unsigned long)vma->vm_end-(unsigned long)vma->vm_start,		rc);	return rc;}static const struct file_operations em28xx_v4l_fops = {	.owner         = THIS_MODULE,	.open          = em28xx_v4l2_open,	.release       = em28xx_v4l2_close,	.read          = em28xx_v4l2_read,	.poll          = em28xx_v4l2_poll,	.mmap          = em28xx_v4l2_mmap,	.ioctl	       = video_ioctl2,	.llseek        = no_llseek,	.compat_ioctl  = v4l_compat_ioctl32,};static const struct v4l2_ioctl_ops video_ioctl_ops = {	.vidioc_querycap            = vidioc_querycap,	.vidioc_enum_fmt_vid_cap    = vidioc_enum_fmt_vid_cap,	.vidioc_g_fmt_vid_cap       = vidioc_g_fmt_vid_cap,	.vidioc_try_fmt_vid_cap     = vidioc_try_fmt_vid_cap,	.vidioc_s_fmt_vid_cap       = vidioc_s_fmt_vid_cap,#if 0	.vidioc_g_fmt_vbi_cap       = vidioc_g_fmt_vbi_cap,	.vidioc_try_fmt_vbi_cap     = vidioc_s_fmt_vbi_cap,	.vidioc_s_fmt_vbi_cap       = vidioc_s_fmt_vbi_cap,#endif	.vidioc_g_audio             = vidioc_g_audio,	.vidioc_s_audio             = vidioc_s_audio,	.vidioc_cropcap             = vidioc_cropcap,	.vidioc_g_fmt_sliced_vbi_cap   = vidioc_g_fmt_sliced_vbi_cap,	.vidioc_try_fmt_sliced_vbi_cap = vidioc_try_set_sliced_vbi_cap,	.vidioc_s_fmt_sliced_vbi_cap   = vidioc_try_set_sliced_vbi_cap,	.vidioc_reqbufs             = vidioc_reqbufs,	.vidioc_querybuf            = vidioc_querybuf,	.vidioc_qbuf                = vidioc_qbuf,	.vidioc_dqbuf               = vidioc_dqbuf,	.vidioc_s_std               = vidioc_s_std,	.vidioc_enum_input          = vidioc_enum_input,	.vidioc_g_input             = vidioc_g_input,	.vidioc_s_input             = vidioc_s_input,	.vidioc_queryctrl           = vidioc_queryctrl,	.vidioc_g_ctrl              = vidioc_g_ctrl,	.vidioc_s_ctrl              = vidioc_s_ctrl,	.vidioc_streamon            = vidioc_streamon,	.vidioc_streamoff           = vidioc_streamoff,	.vidioc_g_tuner             = vidioc_g_tuner,	.vidioc_s_tuner             = vidioc_s_tuner,	.vidioc_g_frequency         = vidioc_g_frequency,	.vidioc_s_frequency         = vidioc_s_frequency,#ifdef CONFIG_VIDEO_ADV_DEBUG	.vidioc_g_register          = vidioc_g_register,	.vidioc_s_register          = vidioc_s_register,#endif#ifdef CONFIG_VIDEO_V4L1_COMPAT	.vidiocgmbuf                = vidiocgmbuf,#endif};static const struct video_device em28xx_video_template = {	.fops                       = &em28xx_v4l_fops,	.release                    = video_device_release,	.ioctl_ops 		    = &video_ioctl_ops,	.minor                      = -1,	.tvnorms                    = V4L2_STD_ALL,	.current_norm               = V4L2_STD_PAL,};static const struct file_operations radio_fops = {	.owner         = THIS_MODULE,	.open          = em28xx_v4l2_open,	.release       = em28xx_v4l2_close,	.ioctl	       = video_ioctl2,	.compat_ioctl  = v4l_compat_ioctl32,	.llseek        = no_llseek,};static const struct v4l2_ioctl_ops radio_ioctl_ops = {	.vidioc_querycap      = radio_querycap,	.vidioc_g_tuner       = radio_g_tuner,	.vidioc_enum_input    = radio_enum_input,	.vidioc_g_audio       = radio_g_audio,	.vidioc_s_tuner       = radio_s_tuner,	.vidioc_s_audio       = radio_s_audio,	.vidioc_s_input       = radio_s_input,	.vidioc_queryctrl     = radio_queryctrl,	.vidioc_g_ctrl        = vidioc_g_ctrl,	.vidioc_s_ctrl        = vidioc_s_ctrl,	.vidioc_g_frequency   = vidioc_g_frequency,	.vidioc_s_frequency   = vidioc_s_frequency,#ifdef CONFIG_VIDEO_ADV_DEBUG	.vidioc_g_register    = vidioc_g_register,	.vidioc_s_register    = vidioc_s_register,#endif};static struct video_device em28xx_radio_template = {	.name                 = "em28xx-radio",	.fops                 = &radio_fops,	.ioctl_ops 	      = &radio_ioctl_ops,	.minor                = -1,};/******************************** usb interface ******************************/static LIST_HEAD(em28xx_extension_devlist);static DEFINE_MUTEX(em28xx_extension_devlist_lock);int em28xx_register_extension(struct em28xx_ops *ops){	struct em28xx *dev = NULL;	mutex_lock(&em28xx_extension_devlist_lock);	list_add_tail(&ops->next, &em28xx_extension_devlist);	list_for_each_entry(dev, &em28xx_devlist, devlist) {		if (dev)			ops->init(dev);	}	printk(KERN_INFO "Em28xx: Initialized (%s) extension\n", ops->name);	mutex_unlock(&em28xx_extension_devlist_lock);	return 0;}EXPORT_SYMBOL(em28xx_register_extension);void em28xx_unregister_extension(struct em28xx_ops *ops){	struct em28xx *dev = NULL;	list_for_each_entry(dev, &em28xx_devlist, devlist) {		if (dev)			ops->fini(dev);	}	mutex_lock(&em28xx_extension_devlist_lock);	printk(KERN_INFO "Em28xx: Removed (%s) extension\n", ops->name);	list_del(&ops->next);	mutex_unlock(&em28xx_extension_devlist_lock);}EXPORT_SYMBOL(em28xx_unregister_extension);static struct video_device *em28xx_vdev_init(struct em28xx *dev,					     const struct video_device *template,					     const char *type_name){	struct video_device *vfd;	vfd = video_device_alloc();	if (NULL == vfd)		return NULL;	*vfd = *template;	vfd->minor   = -1;	vfd->parent = &dev->udev->dev;	vfd->release = video_device_release;	vfd->debug = video_debug;	snprintf(vfd->name, sizeof(vfd->name), "%s %s",		 dev->name, type_name);	return vfd;}/* * em28xx_init_dev() * allocates and inits the device structs, registers i2c bus and v4l device */static int em28xx_init_dev(struct em28xx **devhandle, struct usb_device *udev,			   int minor){	struct em28xx_ops *ops = NULL;	struct em28xx *dev = *devhandle;	int retval = -ENOMEM;	int errCode;	unsigned int maxh, maxw;	dev->udev = udev;	mutex_init(&dev->lock);	spin_lock_init(&dev->slock);	init_waitqueue_head(&dev->open);	init_waitqueue_head(&dev->wait_frame);	init_waitqueue_head(&dev->wait_stream);	dev->em28xx_write_regs = em28xx_write_regs;	dev->em28xx_read_reg = em28xx_read_reg;	dev->em28xx_read_reg_req_len = em28xx_read_reg_req_len;	dev->em28xx_write_regs_req = em28xx_write_regs_req;	dev->em28xx_read_reg_req = em28xx_read_reg_req;	dev->is_em2800 = em28xx_boards[dev->model].is_em2800;	em28xx_pre_card_setup(dev);	errCode = em28xx_config(dev);	if (errCode) {		em28xx_errdev("error configuring device\n");		em28xx_devused &= ~(1<<dev->devno);		kfree(dev);		return -ENOMEM;	}	/* register i2c bus */	errCode = em28xx_i2c_register(dev);	if (errCode < 0) {		em28xx_errdev("%s: em28xx_i2c_register - errCode [%d]!\n",			__func__, errCode);		return errCode;	}	/* Do board specific init and eeprom reading */	em28xx_card_setup(dev);	/* Configure audio */	errCode = em28xx_audio_analog_set(dev);	if (errCode < 0) {		em28xx_errdev("%s: em28xx_audio_analog_set - errCode [%d]!\n",			__func__, errCode);		return errCode;	}	/* configure the device */	em28xx_config_i2c(dev);	/* set default norm */	dev->norm = em28xx_video_template.current_norm;	maxw = norm_maxw(dev);	maxh = norm_maxh(dev);	/* set default image size */	dev->width = maxw;	dev->height = maxh;	dev->interlaced = EM28XX_INTERLACED_DEFAULT;	dev->hscale = 0;	dev->vscale = 0;	dev->ctl_input = 2;	errCode = em28xx_config(dev);	if (errCode < 0) {		em28xx_errdev("%s: em28xx_config - errCode [%d]!\n",			__func__, errCode);		return errCode;	}	list_add_tail(&dev->devlist, &em28xx_devlist);	/* allocate and fill video video_device struct */	dev->vdev = em28xx_vdev_init(dev, &em28xx_video_template, "video");	if (NULL == dev->vdev) {		em28xx_errdev("cannot allocate video_device.\n");		goto fail_unreg;	}	/* register v4l2 video video_device */	retval = video_register_device(dev->vdev, VFL_TYPE_GRABBER,				       video_nr[dev->devno]);	if (retval) {		em28xx_errdev("unable to register video device (error=%i).\n",			      retval);		goto fail_unreg;	}	/* Allocate and fill vbi video_device struct */	dev->vbi_dev = em28xx_vdev_init(dev, &em28xx_video_template, "vbi");	/* register v4l2 vbi video_device */	if (video_register_device(dev->vbi_dev, VFL_TYPE_VBI,					vbi_nr[dev->devno]) < 0) {		em28xx_errdev("unable to register vbi device\n");		retval = -ENODEV;		goto fail_unreg;	}	if (em28xx_boards[dev->model].radio.type == EM28XX_RADIO) {		dev->radio_dev = em28xx_vdev_init(dev, &em28xx_radio_template, "radio");		if (NULL == dev->radio_dev) {			em28xx_errdev("cannot allocate video_device.\n");			goto fail_unreg;		}		retval = video_register_device(dev->radio_dev, VFL_TYPE_RADIO,					    radio_nr[dev->devno]);		if (retval < 0) {			em28xx_errdev("can't register radio device\n");			goto fail_unreg;		}		em28xx_info("Registered radio device as /dev/radio%d\n",			    dev->radio_dev->num);	}	/* init video dma queues */	INIT_LIST_HEAD(&dev->vidq.active);	INIT_LIST_HEAD(&dev->vidq.queued);#if 0	video_set_drvdata(dev->vbi_dev, dev);#endif	if (dev->has_msp34xx) {		/* Send a reset to other chips via gpio */		errCode = em28xx_write_regs_req(dev, 0x00, 0x08, "\xf7", 1);		if (errCode < 0) {			em28xx_errdev("%s: em28xx_write_regs_req - msp34xx(1) failed! errCode [%d]\n",				__func__, errCode);			return errCode;		}		msleep(3);		errCode = em28xx_write_regs_req(dev, 0x00, 0x08, "\xff", 1);		if (errCode < 0) {			em28xx_errdev("%s: em28xx_write_regs_req - msp34xx(2) failed! errCode [%d]\n",				__func__, errCode);			return errCode;		}		msleep(3);	}	video_mux(dev, 0);	em28xx_info("V4L2 device registered as /dev/video%d and /dev/vbi%d\n",				dev->vdev->num, dev->vbi_dev->num);	mutex_lock(&em28xx_extension_devlist_lock);	if (!list_empty(&em28xx_extension_devlist)) {		list_for_each_entry(ops, &em28xx_extension_devlist, next) {			if (ops->id)				ops->init(dev);		}	}	mutex_unlock(&em28xx_extension_devlist_lock);	return 0;fail_unreg:	em28xx_release_resources(dev);	mutex_unlock(&dev->lock);	kfree(dev);	return retval;}#if defined(CONFIG_MODULES) && defined(MODULE)#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20)static void request_module_async(void *ptr){	struct em28xx *dev = (struct em28xx *)ptr;#elsestatic void request_module_async(struct work_struct *work){	struct em28xx *dev = container_of(work,			     struct em28xx, request_module_wk);#endif	if (dev->has_audio_class)		request_module("snd-usb-audio");	else		request_module("em28xx-alsa");	if (dev->has_dvb)		request_module("em28xx-dvb");}static void request_modules(struct em28xx *dev){#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20)	INIT_WORK(&dev->request_module_wk, request_module_async,		  (void *)dev);#else	INIT_WORK(&dev->request_module_wk, request_module_async);#endif	schedule_work(&dev->request_module_wk);}#else#define request_modules(dev)#endif /* CONFIG_MODULES *//* * em28xx_usb_probe() * checks for supported devices */static int em28xx_usb_probe(struct usb_interface *interface,			    const struct usb_device_id *id){	const struct usb_endpoint_descriptor *endpoint;	struct usb_device *udev;	struct usb_interface *uif;	struct em28xx *dev = NULL;	int retval = -ENODEV;	int i, nr, ifnum;	udev = usb_get_dev(interface_to_usbdev(interface));	ifnum = interface->altsetting[0].desc.bInterfaceNumber;	/* Check to see next free device and mark as used */	nr = find_first_zero_bit(&em28xx_devused, EM28XX_MAXBOARDS);	em28xx_devused |= 1<<nr;	/* Don't register audio interfaces */	if (interface->altsetting[0].desc.bInterfaceClass == USB_CLASS_AUDIO) {		em28xx_err(DRIVER_NAME " audio device (%04x:%04x): interface %i, class %i\n",				udev->descriptor.idVendor,				udev->descriptor.idProduct,				ifnum,				interface->altsetting[0].desc.bInterfaceClass);		em28xx_devused &= ~(1<<nr);		return -ENODEV;	}	em28xx_err(DRIVER_NAME " new video device (%04x:%04x): interface %i, class %i\n",			udev->descriptor.idVendor,			udev->descriptor.idProduct,			ifnum,			interface->altsetting[0].desc.bInterfaceClass);	endpoint = &interface->cur_altsetting->endpoint[1].desc;	/* check if the device has the iso in endpoint at the correct place */	if ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) !=	    USB_ENDPOINT_XFER_ISOC) {		em28xx_err(DRIVER_NAME " probing error: endpoint is non-ISO endpoint!\n");		em28xx_devused &= ~(1<<nr);		return -ENODEV;	}	if ((endpoint->bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_OUT) {		em28xx_err(DRIVER_NAME " probing error: endpoint is ISO OUT endpoint!\n");		em28xx_devused &= ~(1<<nr);		return -ENODEV;	}	if (nr >= EM28XX_MAXBOARDS) {		printk(DRIVER_NAME ": Supports only %i em28xx boards.\n",				EM28XX_MAXBOARDS);		em28xx_devused &= ~(1<<nr);		return -ENOMEM;	}	/* allocate memory for our device state and initialize it */	dev = kzalloc(sizeof(*dev), GFP_KERNEL);	if (dev == NULL) {		em28xx_err(DRIVER_NAME ": out of memory!\n");		em28xx_devused &= ~(1<<nr);		return -ENOMEM;	}	snprintf(dev->name, 29, "em28xx #%d", nr);	dev->devno = nr;	dev->model = id->driver_info;	dev->alt   = -1;	/* Checks if audio is provided by some interface */	for (i = 0; i < udev->config->desc.bNumInterfaces; i++) {		uif = udev->config->interface[i];		if (uif->altsetting[0].desc.bInterfaceClass == USB_CLASS_AUDIO) {			dev->has_audio_class = 1;			break;		}	}	printk(KERN_INFO DRIVER_NAME " %s usb audio class\n",		   dev->has_audio_class ? "Has" : "Doesn't have");	/* compute alternate max packet sizes */	uif = udev->actconfig->interface[0];	dev->num_alt = uif->num_altsetting;	em28xx_info("Alternate settings: %i\n", dev->num_alt);/*	dev->alt_max_pkt_size = kmalloc(sizeof(*dev->alt_max_pkt_size)* */	dev->alt_max_pkt_size = kmalloc(32 * dev->num_alt, GFP_KERNEL);	if (dev->alt_max_pkt_size == NULL) {		em28xx_errdev("out of memory!\n");		em28xx_devused &= ~(1<<nr);		kfree(dev);		return -ENOMEM;	}	for (i = 0; i < dev->num_alt ; i++) {		u16 tmp = le16_to_cpu(uif->altsetting[i].endpoint[1].desc.							wMaxPacketSize);		dev->alt_max_pkt_size[i] =		    (tmp & 0x07ff) * (((tmp & 0x1800) >> 11) + 1);		em28xx_info("Alternate setting %i, max size= %i\n", i,						dev->alt_max_pkt_size[i]);	}	if ((card[nr] >= 0) && (card[nr] < em28xx_bcount))		dev->model = card[nr];	/* allocate device struct */	retval = em28xx_init_dev(&dev, udev, nr);	if (retval)		return retval;	em28xx_info("Found %s\n", em28xx_boards[dev->model].name);	/* save our data pointer in this interface device */	usb_set_intfdata(interface, dev);	request_modules(dev);	return 0;}/* * em28xx_usb_disconnect() * called when the device gets diconencted * video device will be unregistered on v4l2_close in case it is still open */static void em28xx_usb_disconnect(struct usb_interface *interface){	struct em28xx *dev;	struct em28xx_ops *ops = NULL;	dev = usb_get_intfdata(interface);	usb_set_intfdata(interface, NULL);	if (!dev)		return;	em28xx_info("disconnecting %s\n", dev->vdev->name);	/* wait until all current v4l2 io is finished then deallocate	   resources */	mutex_lock(&dev->lock);	wake_up_interruptible_all(&dev->open);	if (dev->users) {		em28xx_warn		    ("device /dev/video%d is open! Deregistration and memory "		     "deallocation are deferred on close.\n",				dev->vdev->num);		dev->state |= DEV_MISCONFIGURED;		em28xx_uninit_isoc(dev);		dev->state |= DEV_DISCONNECTED;		wake_up_interruptible(&dev->wait_frame);		wake_up_interruptible(&dev->wait_stream);	} else {		dev->state |= DEV_DISCONNECTED;		em28xx_release_resources(dev);	}	mutex_unlock(&dev->lock);	mutex_lock(&em28xx_extension_devlist_lock);	if (!list_empty(&em28xx_extension_devlist)) {		list_for_each_entry(ops, &em28xx_extension_devlist, next) {			ops->fini(dev);		}	}	mutex_unlock(&em28xx_extension_devlist_lock);	if (!dev->users) {		kfree(dev->alt_max_pkt_size);		kfree(dev);	}}static struct usb_driver em28xx_usb_driver = {	.name = "em28xx",	.probe = em28xx_usb_probe,	.disconnect = em28xx_usb_disconnect,	.id_table = em28xx_id_table,};static int __init em28xx_module_init(void){	int result;	printk(KERN_INFO DRIVER_NAME " v4l2 driver version %d.%d.%d loaded\n",	       (EM28XX_VERSION_CODE >> 16) & 0xff,	       (EM28XX_VERSION_CODE >> 8) & 0xff, EM28XX_VERSION_CODE & 0xff);#ifdef SNAPSHOT	printk(KERN_INFO DRIVER_NAME " snapshot date %04d-%02d-%02d\n",	       SNAPSHOT / 10000, (SNAPSHOT / 100) % 100, SNAPSHOT % 100);#endif	/* register this driver with the USB subsystem */	result = usb_register(&em28xx_usb_driver);	if (result)		em28xx_err(DRIVER_NAME			   " usb_register failed. Error number %d.\n", result);	return result;}static void __exit em28xx_module_exit(void){	/* deregister this driver with the USB subsystem */	usb_deregister(&em28xx_usb_driver);}module_init(em28xx_module_init);module_exit(em28xx_module_exit);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -