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

📄 em28xx-video.c

📁 linux2.6.16版本
💻 C
📖 第 1 页 / 共 4 页
字号:
			if (rb->count)				rb->count =				    em28xx_request_buffers(dev, rb->count);			dev->frame_current = NULL;			em28xx_videodbg ("VIDIOC_REQBUFS: setting io method to mmap: num bufs %i\n",						     rb->count);			dev->io = rb->count ? IO_MMAP : IO_NONE;			return 0;		}	case VIDIOC_QUERYBUF:		{			struct v4l2_buffer *b = arg;			if (b->type != V4L2_BUF_TYPE_VIDEO_CAPTURE ||			    b->index >= dev->num_frames || dev->io != IO_MMAP)				return -EINVAL;			memcpy(b, &dev->frame[b->index].buf, sizeof(*b));			if (dev->frame[b->index].vma_use_count) {				b->flags |= V4L2_BUF_FLAG_MAPPED;			}			if (dev->frame[b->index].state == F_DONE)				b->flags |= V4L2_BUF_FLAG_DONE;			else if (dev->frame[b->index].state != F_UNUSED)				b->flags |= V4L2_BUF_FLAG_QUEUED;			return 0;		}	case VIDIOC_QBUF:		{			struct v4l2_buffer *b = arg;			unsigned long lock_flags;			if (b->type != V4L2_BUF_TYPE_VIDEO_CAPTURE ||			    b->index >= dev->num_frames || dev->io != IO_MMAP) {				return -EINVAL;			}			if (dev->frame[b->index].state != F_UNUSED) {				return -EAGAIN;			}			dev->frame[b->index].state = F_QUEUED;			/* add frame to fifo */			spin_lock_irqsave(&dev->queue_lock, lock_flags);			list_add_tail(&dev->frame[b->index].frame,				      &dev->inqueue);			spin_unlock_irqrestore(&dev->queue_lock, lock_flags);			return 0;		}	case VIDIOC_DQBUF:		{			struct v4l2_buffer *b = arg;			struct em28xx_frame_t *f;			unsigned long lock_flags;			int ret = 0;			if (b->type != V4L2_BUF_TYPE_VIDEO_CAPTURE			    || dev->io != IO_MMAP)				return -EINVAL;			if (list_empty(&dev->outqueue)) {				if (dev->stream == STREAM_OFF)					return -EINVAL;				if (filp->f_flags & O_NONBLOCK)					return -EAGAIN;				ret = wait_event_interruptible				    (dev->wait_frame,				     (!list_empty(&dev->outqueue)) ||				     (dev->state & DEV_DISCONNECTED));				if (ret)					return ret;				if (dev->state & DEV_DISCONNECTED)					return -ENODEV;			}			spin_lock_irqsave(&dev->queue_lock, lock_flags);			f = list_entry(dev->outqueue.next,				       struct em28xx_frame_t, frame);			list_del(dev->outqueue.next);			spin_unlock_irqrestore(&dev->queue_lock, lock_flags);			f->state = F_UNUSED;			memcpy(b, &f->buf, sizeof(*b));			if (f->vma_use_count)				b->flags |= V4L2_BUF_FLAG_MAPPED;			return 0;		}	default:		return em28xx_do_ioctl(inode, filp, dev, cmd, arg,				       em28xx_video_do_ioctl);	}	return 0;}/* * em28xx_v4l2_ioctl() * handle v4l2 ioctl the main action happens in em28xx_v4l2_do_ioctl() */static int em28xx_v4l2_ioctl(struct inode *inode, struct file *filp,			     unsigned int cmd, unsigned long arg){	int ret = 0;	struct em28xx *dev = filp->private_data;	if (down_interruptible(&dev->fileop_lock))		return -ERESTARTSYS;	if (dev->state & DEV_DISCONNECTED) {		em28xx_errdev("v4l2 ioctl: device not present\n");		up(&dev->fileop_lock);		return -ENODEV;	}	if (dev->state & DEV_MISCONFIGURED) {		em28xx_errdev		    ("v4l2 ioctl: device is misconfigured; close and open it again\n");		up(&dev->fileop_lock);		return -EIO;	}	ret = video_usercopy(inode, filp, cmd, arg, em28xx_video_do_ioctl);	up(&dev->fileop_lock);	return ret;}static struct file_operations em28xx_v4l_fops = {	.owner = THIS_MODULE,	.open = em28xx_v4l2_open,	.release = em28xx_v4l2_close,	.ioctl = em28xx_v4l2_ioctl,	.read = em28xx_v4l2_read,	.poll = em28xx_v4l2_poll,	.mmap = em28xx_v4l2_mmap,	.llseek = no_llseek,	.compat_ioctl   = v4l_compat_ioctl32,};/******************************** usb interface *****************************************//* * 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, int model){	struct em28xx *dev = *devhandle;	int retval = -ENOMEM;	int errCode, i;	unsigned int maxh, maxw;	dev->udev = udev;	dev->model = model;	init_MUTEX(&dev->lock);	init_waitqueue_head(&dev->open);	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[model].is_em2800;	dev->has_tuner = em28xx_boards[model].has_tuner;	dev->has_msp34xx = em28xx_boards[model].has_msp34xx;	dev->tda9887_conf = em28xx_boards[model].tda9887_conf;	dev->decoder = em28xx_boards[model].decoder;	if (tuner >= 0)		dev->tuner_type = tuner;	else		dev->tuner_type = em28xx_boards[model].tuner_type;	dev->video_inputs = em28xx_boards[model].vchannels;	for (i = 0; i < TVNORMS; i++)		if (em28xx_boards[model].norm == tvnorms[i].mode)			break;	if (i == TVNORMS)		i = 0;	dev->tvnorm = &tvnorms[i];	/* set default norm */	em28xx_videodbg("tvnorm=%s\n", dev->tvnorm->name);	maxw = norm_maxw(dev);	maxh = norm_maxh(dev);	/* set default image size */	dev->width = maxw;	dev->height = maxh;	dev->interlaced = EM28XX_INTERLACED_DEFAULT;	dev->field_size = dev->width * dev->height;	dev->frame_size =	    dev->interlaced ? dev->field_size << 1 : dev->field_size;	dev->bytesperline = dev->width * 2;	dev->hscale = 0;	dev->vscale = 0;	dev->ctl_input = 2;	/* setup video picture settings for saa7113h */	memset(&dev->vpic, 0, sizeof(dev->vpic));	dev->vpic.colour = 128 << 8;	dev->vpic.hue = 128 << 8;	dev->vpic.brightness = 128 << 8;	dev->vpic.contrast = 192 << 8;	dev->vpic.whiteness = 128 << 8;	/* This one isn't used */	dev->vpic.depth = 16;	dev->vpic.palette = VIDEO_PALETTE_YUV422;#ifdef CONFIG_MODULES	/* request some modules */	if (dev->decoder == EM28XX_SAA7113 || dev->decoder == EM28XX_SAA7114)		request_module("saa711x");	if (dev->decoder == EM28XX_TVP5150)		request_module("tvp5150");	if (dev->has_tuner)		request_module("tuner");	if (dev->tda9887_conf)		request_module("tda9887");#endif	errCode = em28xx_config(dev);	if (errCode) {		em28xx_errdev("error configuring device\n");		kfree(dev);		return -ENOMEM;	}	down(&dev->lock);	/* register i2c bus */	em28xx_i2c_register(dev);	/* Do board specific init and eeprom reading */	em28xx_card_setup(dev);	/* configure the device */	em28xx_config_i2c(dev);	up(&dev->lock);	errCode = em28xx_config(dev);#ifdef CONFIG_MODULES	if (dev->has_msp34xx)		request_module("msp3400");#endif	/* allocate and fill v4l2 device struct */	dev->vdev = video_device_alloc();	if (NULL == dev->vdev) {		em28xx_errdev("cannot allocate video_device.\n");		kfree(dev);		return -ENOMEM;	}	dev->vdev->type = VID_TYPE_CAPTURE;	if (dev->has_tuner)		dev->vdev->type |= VID_TYPE_TUNER;	dev->vdev->hardware = 0;	dev->vdev->fops = &em28xx_v4l_fops;	dev->vdev->minor = -1;	dev->vdev->dev = &dev->udev->dev;	dev->vdev->release = video_device_release;	snprintf(dev->vdev->name, sizeof(dev->vdev->name), "%s",		 "em28xx video");	list_add_tail(&dev->devlist,&em28xx_devlist);	/* register v4l2 device */	down(&dev->lock);	if ((retval = video_register_device(dev->vdev, VFL_TYPE_GRABBER, -1))) {		em28xx_errdev("unable to register video device (error=%i).\n",			      retval);		up(&dev->lock);		list_del(&dev->devlist);		video_device_release(dev->vdev);		kfree(dev);		return -ENODEV;	}	if (dev->has_msp34xx) {		/* Send a reset to other chips via gpio */		em28xx_write_regs_req(dev, 0x00, 0x08, "\xf7", 1);		udelay(2500);		em28xx_write_regs_req(dev, 0x00, 0x08, "\xff", 1);		udelay(2500);	}	video_mux(dev, 0);	up(&dev->lock);	em28xx_info("V4L2 device registered as /dev/video%d\n",		    dev->vdev->minor);	return 0;}/* * 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 model,i,nr,ifnum;	udev = usb_get_dev(interface_to_usbdev(interface));	ifnum = interface->altsetting[0].desc.bInterfaceNumber;	/* 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);		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 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");		return -ENODEV;	}	if ((endpoint->bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_OUT) {		em28xx_err(DRIVER_NAME " probing error: endpoint is ISO OUT endpoint!\n");		return -ENODEV;	}	model=id->driver_info;	nr=interface->minor;	if (nr>EM28XX_MAXBOARDS) {		printk (DRIVER_NAME ": Supports only %i em28xx boards.\n",EM28XX_MAXBOARDS);		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");		return -ENOMEM;	}	/* compute alternate max packet sizes */	uif = udev->actconfig->interface[0];	dev->num_alt=uif->num_altsetting;	printk(DRIVER_NAME ": 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_err(DRIVER_NAME ": out of memory!\n");		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);		printk(DRIVER_NAME ": Alternate setting %i, max size= %i\n",i,							dev->alt_max_pkt_size[i]);	}	snprintf(dev->name, 29, "em28xx #%d", nr);	if ((card[nr]>=0)&&(card[nr]<em28xx_bcount))		model=card[nr];	if ((model==EM2800_BOARD_UNKNOWN)||(model==EM2820_BOARD_UNKNOWN)) {		printk( "%s: Your board has no eeprom inside it and thus can't\n"			"%s: be autodetected.  Please pass card=<n> insmod option to\n"			"%s: workaround that.  Redirect complaints to the vendor of\n"			"%s: the TV card.  Best regards,\n"			"%s:         -- tux\n",			dev->name,dev->name,dev->name,dev->name,dev->name);		printk("%s: Here is a list of valid choices for the card=<n> insmod option:\n",			dev->name);		for (i = 0; i < em28xx_bcount; i++) {			printk("%s:    card=%d -> %s\n",				dev->name, i, em28xx_boards[i].name);		}	}	/* allocate device struct */	retval = em28xx_init_dev(&dev, udev, nr, model);	if (retval)		return retval;	em28xx_info("Found %s\n", em28xx_boards[model].name);	/* save our data pointer in this interface device */	usb_set_intfdata(interface, 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 = usb_get_intfdata(interface);	usb_set_intfdata(interface, NULL);/*FIXME: IR should be disconnected */	if (!dev)		return;	down_write(&em28xx_disconnect);	down(&dev->lock);	em28xx_info("disconnecting %s\n", dev->vdev->name);	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->minor);		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);	}	up(&dev->lock);	if (!dev->users) {		kfree(dev->alt_max_pkt_size);		kfree(dev);	}	up_write(&em28xx_disconnect);}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 + -