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

📄 stk-webcam.c

📁 trident tm5600的linux驱动
💻 C
📖 第 1 页 / 共 3 页
字号:
	pix_format->pixelformat = dev->vsettings.palette;	if (dev->vsettings.palette == V4L2_PIX_FMT_SBGGR8)		pix_format->bytesperline = pix_format->width;	else		pix_format->bytesperline = 2 * pix_format->width;	pix_format->sizeimage = pix_format->bytesperline				* pix_format->height;	return 0;}static int stk_vidioc_try_fmt_vid_cap(struct file *filp,		void *priv, struct v4l2_format *fmtd){	int i;	switch (fmtd->fmt.pix.pixelformat) {	case V4L2_PIX_FMT_RGB565:	case V4L2_PIX_FMT_RGB565X:	case V4L2_PIX_FMT_UYVY:	case V4L2_PIX_FMT_YUYV:	case V4L2_PIX_FMT_SBGGR8:		break;	default:		return -EINVAL;	}	for (i = 1; i < ARRAY_SIZE(stk_sizes); i++) {		if (fmtd->fmt.pix.width > stk_sizes[i].w)			break;	}	if (i == ARRAY_SIZE(stk_sizes)		|| (abs(fmtd->fmt.pix.width - stk_sizes[i-1].w)			< abs(fmtd->fmt.pix.width - stk_sizes[i].w))) {		fmtd->fmt.pix.height = stk_sizes[i-1].h;		fmtd->fmt.pix.width = stk_sizes[i-1].w;		fmtd->fmt.pix.priv = i - 1;	} else {		fmtd->fmt.pix.height = stk_sizes[i].h;		fmtd->fmt.pix.width = stk_sizes[i].w;		fmtd->fmt.pix.priv = i;	}	fmtd->fmt.pix.field = V4L2_FIELD_NONE;	fmtd->fmt.pix.colorspace = V4L2_COLORSPACE_SRGB;	if (fmtd->fmt.pix.pixelformat == V4L2_PIX_FMT_SBGGR8)		fmtd->fmt.pix.bytesperline = fmtd->fmt.pix.width;	else		fmtd->fmt.pix.bytesperline = 2 * fmtd->fmt.pix.width;	fmtd->fmt.pix.sizeimage = fmtd->fmt.pix.bytesperline		* fmtd->fmt.pix.height;	return 0;}static int stk_setup_format(struct stk_camera *dev){	int i = 0;	int depth;	if (dev->vsettings.palette == V4L2_PIX_FMT_SBGGR8)		depth = 1;	else		depth = 2;	while (stk_sizes[i].m != dev->vsettings.mode			&& i < ARRAY_SIZE(stk_sizes))		i++;	if (i == ARRAY_SIZE(stk_sizes)) {		STK_ERROR("Something is broken in %s\n", __func__);		return -EFAULT;	}	/* This registers controls some timings, not sure of what. */	stk_camera_write_reg(dev, 0x001b, 0x0e);	if (dev->vsettings.mode == MODE_SXGA)		stk_camera_write_reg(dev, 0x001c, 0x0e);	else		stk_camera_write_reg(dev, 0x001c, 0x46);	/*	 * Registers 0x0115 0x0114 are the size of each line (bytes),	 * regs 0x0117 0x0116 are the heigth of the image.	 */	stk_camera_write_reg(dev, 0x0115,		((stk_sizes[i].w * depth) >> 8) & 0xff);	stk_camera_write_reg(dev, 0x0114,		(stk_sizes[i].w * depth) & 0xff);	stk_camera_write_reg(dev, 0x0117,		(stk_sizes[i].h >> 8) & 0xff);	stk_camera_write_reg(dev, 0x0116,		stk_sizes[i].h & 0xff);	return stk_sensor_configure(dev);}static int stk_vidioc_s_fmt_vid_cap(struct file *filp,		void *priv, struct v4l2_format *fmtd){	int ret;	struct stk_camera *dev = priv;	if (dev == NULL)		return -ENODEV;	if (!is_present(dev))		return -ENODEV;	if (is_streaming(dev))		return -EBUSY;	if (dev->owner && dev->owner != filp)		return -EBUSY;	ret = stk_vidioc_try_fmt_vid_cap(filp, priv, fmtd);	if (ret)		return ret;	dev->owner = filp;	dev->vsettings.palette = fmtd->fmt.pix.pixelformat;	stk_free_buffers(dev);	dev->frame_size = fmtd->fmt.pix.sizeimage;	dev->vsettings.mode = stk_sizes[fmtd->fmt.pix.priv].m;	stk_initialise(dev);	return stk_setup_format(dev);}static int stk_vidioc_reqbufs(struct file *filp,		void *priv, struct v4l2_requestbuffers *rb){	struct stk_camera *dev = priv;	if (dev == NULL)		return -ENODEV;	if (rb->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)		return -EINVAL;	if (rb->memory != V4L2_MEMORY_MMAP)		return -EINVAL;	if (is_streaming(dev)		|| (dev->owner && dev->owner != filp))		return -EBUSY;	dev->owner = filp;	/*FIXME If they ask for zero, we must stop streaming and free */	if (rb->count < 3)		rb->count = 3;	/* Arbitrary limit */	else if (rb->count > 5)		rb->count = 5;	stk_allocate_buffers(dev, rb->count);	rb->count = dev->n_sbufs;	return 0;}static int stk_vidioc_querybuf(struct file *filp,		void *priv, struct v4l2_buffer *buf){	int index;	struct stk_camera *dev = priv;	struct stk_sio_buffer *sbuf;	if (buf->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)		return -EINVAL;	index = buf->index;	if (index < 0 || index >= dev->n_sbufs)		return -EINVAL;	sbuf = dev->sio_bufs + buf->index;	*buf = sbuf->v4lbuf;	return 0;}static int stk_vidioc_qbuf(struct file *filp,		void *priv, struct v4l2_buffer *buf){	struct stk_camera *dev = priv;	struct stk_sio_buffer *sbuf;	unsigned long flags;	if (buf->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)		return -EINVAL;	if (buf->memory != V4L2_MEMORY_MMAP)		return -EINVAL;	if (buf->index < 0 || buf->index >= dev->n_sbufs)		return -EINVAL;	sbuf = dev->sio_bufs + buf->index;	if (sbuf->v4lbuf.flags & V4L2_BUF_FLAG_QUEUED)		return 0;	sbuf->v4lbuf.flags |= V4L2_BUF_FLAG_QUEUED;	sbuf->v4lbuf.flags &= ~V4L2_BUF_FLAG_DONE;	spin_lock_irqsave(&dev->spinlock, flags);	list_add_tail(&sbuf->list, &dev->sio_avail);	*buf = sbuf->v4lbuf;	spin_unlock_irqrestore(&dev->spinlock, flags);	return 0;}static int stk_vidioc_dqbuf(struct file *filp,		void *priv, struct v4l2_buffer *buf){	struct stk_camera *dev = priv;	struct stk_sio_buffer *sbuf;	unsigned long flags;	int ret;	if (buf->type != V4L2_BUF_TYPE_VIDEO_CAPTURE		|| !is_streaming(dev))		return -EINVAL;	if (filp->f_flags & O_NONBLOCK && list_empty(&dev->sio_full))		return -EWOULDBLOCK;	ret = wait_event_interruptible(dev->wait_frame,		!list_empty(&dev->sio_full) || !is_present(dev));	if (ret)		return ret;	if (!is_present(dev))		return -EIO;	spin_lock_irqsave(&dev->spinlock, flags);	sbuf = list_first_entry(&dev->sio_full, struct stk_sio_buffer, list);	list_del_init(&sbuf->list);	spin_unlock_irqrestore(&dev->spinlock, flags);	sbuf->v4lbuf.flags &= ~V4L2_BUF_FLAG_QUEUED;	sbuf->v4lbuf.flags |= V4L2_BUF_FLAG_DONE;	sbuf->v4lbuf.sequence = ++dev->sequence;	do_gettimeofday(&sbuf->v4lbuf.timestamp);	*buf = sbuf->v4lbuf;	return 0;}static int stk_vidioc_streamon(struct file *filp,		void *priv, enum v4l2_buf_type type){	struct stk_camera *dev = priv;	if (is_streaming(dev))		return 0;	if (dev->sio_bufs == NULL)		return -EINVAL;	dev->sequence = 0;	return stk_start_stream(dev);}static int stk_vidioc_streamoff(struct file *filp,		void *priv, enum v4l2_buf_type type){	struct stk_camera *dev = priv;	unsigned long flags;	int i;	stk_stop_stream(dev);	spin_lock_irqsave(&dev->spinlock, flags);	INIT_LIST_HEAD(&dev->sio_avail);	INIT_LIST_HEAD(&dev->sio_full);	for (i = 0; i < dev->n_sbufs; i++) {		INIT_LIST_HEAD(&dev->sio_bufs[i].list);		dev->sio_bufs[i].v4lbuf.flags = 0;	}	spin_unlock_irqrestore(&dev->spinlock, flags);	return 0;}static int stk_vidioc_g_parm(struct file *filp,		void *priv, struct v4l2_streamparm *sp){	if (sp->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)		return -EINVAL;	sp->parm.capture.capability = 0;	sp->parm.capture.capturemode = 0;	/*FIXME This is not correct */	sp->parm.capture.timeperframe.numerator = 1;	sp->parm.capture.timeperframe.denominator = 30;	sp->parm.capture.readbuffers = 2;	sp->parm.capture.extendedmode = 0;	return 0;}static struct file_operations v4l_stk_fops = {	.owner = THIS_MODULE,	.open = v4l_stk_open,	.release = v4l_stk_release,	.read = v4l_stk_read,	.poll = v4l_stk_poll,	.mmap = v4l_stk_mmap,	.ioctl = video_ioctl2,#ifdef CONFIG_COMPAT	.compat_ioctl = v4l_compat_ioctl32,#endif	.llseek = no_llseek};static const struct v4l2_ioctl_ops v4l_stk_ioctl_ops = {	.vidioc_querycap = stk_vidioc_querycap,	.vidioc_enum_fmt_vid_cap = stk_vidioc_enum_fmt_vid_cap,	.vidioc_try_fmt_vid_cap = stk_vidioc_try_fmt_vid_cap,	.vidioc_s_fmt_vid_cap = stk_vidioc_s_fmt_vid_cap,	.vidioc_g_fmt_vid_cap = stk_vidioc_g_fmt_vid_cap,	.vidioc_enum_input = stk_vidioc_enum_input,	.vidioc_s_input = stk_vidioc_s_input,	.vidioc_g_input = stk_vidioc_g_input,	.vidioc_s_std = stk_vidioc_s_std,	.vidioc_reqbufs = stk_vidioc_reqbufs,	.vidioc_querybuf = stk_vidioc_querybuf,	.vidioc_qbuf = stk_vidioc_qbuf,	.vidioc_dqbuf = stk_vidioc_dqbuf,	.vidioc_streamon = stk_vidioc_streamon,	.vidioc_streamoff = stk_vidioc_streamoff,	.vidioc_queryctrl = stk_vidioc_queryctrl,	.vidioc_g_ctrl = stk_vidioc_g_ctrl,	.vidioc_s_ctrl = stk_vidioc_s_ctrl,	.vidioc_g_parm = stk_vidioc_g_parm,};static void stk_v4l_dev_release(struct video_device *vd){	struct stk_camera *dev = vdev_to_camera(vd);	if (dev->sio_bufs != NULL || dev->isobufs != NULL)		STK_ERROR("We are leaking memory\n");	usb_put_intf(dev->interface);	kfree(dev);}static struct video_device stk_v4l_data = {	.name = "stkwebcam",	.minor = -1,	.tvnorms = V4L2_STD_UNKNOWN,	.current_norm = V4L2_STD_UNKNOWN,	.fops = &v4l_stk_fops,	.ioctl_ops = &v4l_stk_ioctl_ops,	.release = stk_v4l_dev_release,};static int stk_register_video_device(struct stk_camera *dev){	int err;	dev->vdev = stk_v4l_data;	dev->vdev.debug = debug;	dev->vdev.parent = &dev->interface->dev;	err = video_register_device(&dev->vdev, VFL_TYPE_GRABBER, -1);	if (err)		STK_ERROR("v4l registration failed\n");	else		STK_INFO("Syntek USB2.0 Camera is now controlling video device"			" /dev/video%d\n", dev->vdev.num);	return err;}/* USB Stuff */static int stk_camera_probe(struct usb_interface *interface,		const struct usb_device_id *id){	int i;	int err = 0;	struct stk_camera *dev = NULL;	struct usb_device *udev = interface_to_usbdev(interface);	struct usb_host_interface *iface_desc;	struct usb_endpoint_descriptor *endpoint;	dev = kzalloc(sizeof(struct stk_camera), GFP_KERNEL);	if (dev == NULL) {		STK_ERROR("Out of memory !\n");		return -ENOMEM;	}	spin_lock_init(&dev->spinlock);	init_waitqueue_head(&dev->wait_frame);	dev->udev = udev;	dev->interface = interface;	usb_get_intf(interface);	dev->vsettings.vflip = vflip;	dev->vsettings.hflip = hflip;	dev->n_sbufs = 0;	set_present(dev);	/* Set up the endpoint information	 * use only the first isoc-in endpoint	 * for the current alternate setting */	iface_desc = interface->cur_altsetting;	for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) {		endpoint = &iface_desc->endpoint[i].desc;		if (!dev->isoc_ep			&& ((endpoint->bEndpointAddress				& USB_ENDPOINT_DIR_MASK) == USB_DIR_IN)			&& ((endpoint->bmAttributes				& USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_ISOC)) {			/* we found an isoc in endpoint */			dev->isoc_ep = (endpoint->bEndpointAddress & 0xF);			break;		}	}	if (!dev->isoc_ep) {		STK_ERROR("Could not find isoc-in endpoint");		err = -ENODEV;		goto error;	}	dev->vsettings.brightness = 0x7fff;	dev->vsettings.palette = V4L2_PIX_FMT_RGB565;	dev->vsettings.mode = MODE_VGA;	dev->frame_size = 640 * 480 * 2;	INIT_LIST_HEAD(&dev->sio_avail);	INIT_LIST_HEAD(&dev->sio_full);	usb_set_intfdata(interface, dev);	err = stk_register_video_device(dev);	if (err) {		goto error;	}	stk_create_sysfs_files(&dev->vdev);	usb_autopm_enable(dev->interface);	return 0;error:	kfree(dev);	return err;}static void stk_camera_disconnect(struct usb_interface *interface){	struct stk_camera *dev = usb_get_intfdata(interface);	usb_set_intfdata(interface, NULL);	unset_present(dev);	wake_up_interruptible(&dev->wait_frame);	stk_remove_sysfs_files(&dev->vdev);	STK_INFO("Syntek USB2.0 Camera release resources "		"video device /dev/video%d\n", dev->vdev.num);	video_unregister_device(&dev->vdev);}#ifdef CONFIG_PMstatic int stk_camera_suspend(struct usb_interface *intf, pm_message_t message){	struct stk_camera *dev = usb_get_intfdata(intf);	if (is_streaming(dev)) {		stk_stop_stream(dev);		/* yes, this is ugly */		set_streaming(dev);	}	return 0;}static int stk_camera_resume(struct usb_interface *intf){	struct stk_camera *dev = usb_get_intfdata(intf);	if (!is_initialised(dev))		return 0;	unset_initialised(dev);	stk_initialise(dev);	stk_setup_format(dev);	if (is_streaming(dev))		stk_start_stream(dev);	return 0;}#endifstatic struct usb_driver stk_camera_driver = {	.name = "stkwebcam",	.probe = stk_camera_probe,	.disconnect = stk_camera_disconnect,	.id_table = stkwebcam_table,#ifdef CONFIG_PM	.suspend = stk_camera_suspend,	.resume = stk_camera_resume,#endif};static int __init stk_camera_init(void){	int result;	result = usb_register(&stk_camera_driver);	if (result)		STK_ERROR("usb_register failed ! Error number %d\n", result);	return result;}static void __exit stk_camera_exit(void){	usb_deregister(&stk_camera_driver);}module_init(stk_camera_init);module_exit(stk_camera_exit);

⌨️ 快捷键说明

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