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

📄 stk-webcam.c

📁 trident tm5600的linux驱动
💻 C
📖 第 1 页 / 共 3 页
字号:
	for (i = 0; i < MAX_ISO_BUFS; i++) {		if (dev->isobufs[i].data == NULL) {			kbuf = kzalloc(ISO_BUFFER_SIZE, GFP_KERNEL);			if (kbuf == NULL) {				STK_ERROR("Failed to allocate iso buffer %d\n",					i);				goto isobufs_out;			}			dev->isobufs[i].data = kbuf;		} else			STK_ERROR("isobuf data already allocated\n");		if (dev->isobufs[i].urb == NULL) {			urb = usb_alloc_urb(ISO_FRAMES_PER_DESC, GFP_KERNEL);			if (urb == NULL) {				STK_ERROR("Failed to allocate URB %d\n", i);				goto isobufs_out;			}			dev->isobufs[i].urb = urb;		} else {			STK_ERROR("Killing URB\n");			usb_kill_urb(dev->isobufs[i].urb);			urb = dev->isobufs[i].urb;		}		urb->interval = 1;		urb->dev = udev;		urb->pipe = usb_rcvisocpipe(udev, dev->isoc_ep);		urb->transfer_flags = URB_ISO_ASAP;		urb->transfer_buffer = dev->isobufs[i].data;		urb->transfer_buffer_length = ISO_BUFFER_SIZE;		urb->complete = stk_isoc_handler;		urb->context = dev;		urb->start_frame = 0;		urb->number_of_packets = ISO_FRAMES_PER_DESC;		for (j = 0; j < ISO_FRAMES_PER_DESC; j++) {			urb->iso_frame_desc[j].offset = j * ISO_MAX_FRAME_SIZE;			urb->iso_frame_desc[j].length = ISO_MAX_FRAME_SIZE;		}	}	set_memallocd(dev);	return 0;isobufs_out:	for (i = 0; i < MAX_ISO_BUFS && dev->isobufs[i].data; i++)		kfree(dev->isobufs[i].data);	for (i = 0; i < MAX_ISO_BUFS && dev->isobufs[i].urb; i++)		usb_free_urb(dev->isobufs[i].urb);	kfree(dev->isobufs);	dev->isobufs = NULL;	return -ENOMEM;}static void stk_clean_iso(struct stk_camera *dev){	int i;	if (dev == NULL || dev->isobufs == NULL)		return;	for (i = 0; i < MAX_ISO_BUFS; i++) {		struct urb *urb;		urb = dev->isobufs[i].urb;		if (urb) {			if (atomic_read(&dev->urbs_used) && is_present(dev))				usb_kill_urb(urb);			usb_free_urb(urb);		}		kfree(dev->isobufs[i].data);	}	kfree(dev->isobufs);	dev->isobufs = NULL;	unset_memallocd(dev);}static int stk_setup_siobuf(struct stk_camera *dev, int index){	struct stk_sio_buffer *buf = dev->sio_bufs + index;	INIT_LIST_HEAD(&buf->list);	buf->v4lbuf.length = PAGE_ALIGN(dev->frame_size);	buf->buffer = vmalloc_user(buf->v4lbuf.length);	if (buf->buffer == NULL)		return -ENOMEM;	buf->mapcount = 0;	buf->dev = dev;	buf->v4lbuf.index = index;	buf->v4lbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;	buf->v4lbuf.field = V4L2_FIELD_NONE;	buf->v4lbuf.memory = V4L2_MEMORY_MMAP;	buf->v4lbuf.m.offset = 2*index*buf->v4lbuf.length;	return 0;}static int stk_free_sio_buffers(struct stk_camera *dev){	int i;	int nbufs;	unsigned long flags;	if (dev->n_sbufs == 0 || dev->sio_bufs == NULL)		return 0;	/*	* If any buffers are mapped, we cannot free them at all.	*/	for (i = 0; i < dev->n_sbufs; i++) {		if (dev->sio_bufs[i].mapcount > 0)			return -EBUSY;	}	/*	* OK, let's do it.	*/	spin_lock_irqsave(&dev->spinlock, flags);	INIT_LIST_HEAD(&dev->sio_avail);	INIT_LIST_HEAD(&dev->sio_full);	nbufs = dev->n_sbufs;	dev->n_sbufs = 0;	spin_unlock_irqrestore(&dev->spinlock, flags);	for (i = 0; i < nbufs; i++) {		if (dev->sio_bufs[i].buffer != NULL)			vfree(dev->sio_bufs[i].buffer);	}	kfree(dev->sio_bufs);	dev->sio_bufs = NULL;	return 0;}static int stk_prepare_sio_buffers(struct stk_camera *dev, unsigned n_sbufs){	int i;	if (dev->sio_bufs != NULL)		STK_ERROR("sio_bufs already allocated\n");	else {		dev->sio_bufs = kzalloc(n_sbufs * sizeof(struct stk_sio_buffer),				GFP_KERNEL);		if (dev->sio_bufs == NULL)			return -ENOMEM;		for (i = 0; i < n_sbufs; i++) {			if (stk_setup_siobuf(dev, i))				return (dev->n_sbufs > 1)? 0 : -ENOMEM;			dev->n_sbufs = i+1;		}	}	return 0;}static int stk_allocate_buffers(struct stk_camera *dev, unsigned n_sbufs){	int err;	err = stk_prepare_iso(dev);	if (err) {		stk_clean_iso(dev);		return err;	}	err = stk_prepare_sio_buffers(dev, n_sbufs);	if (err) {		stk_free_sio_buffers(dev);		return err;	}	return 0;}static void stk_free_buffers(struct stk_camera *dev){	stk_clean_iso(dev);	stk_free_sio_buffers(dev);}/* -------------------------------------------- *//* v4l file operations */static int v4l_stk_open(struct inode *inode, struct file *fp){	struct stk_camera *dev;	struct video_device *vdev;	vdev = video_devdata(fp);	dev = vdev_to_camera(vdev);	lock_kernel();	if (dev == NULL || !is_present(dev)) {		unlock_kernel();		return -ENXIO;	}	fp->private_data = dev;	usb_autopm_get_interface(dev->interface);	unlock_kernel();	return 0;}static int v4l_stk_release(struct inode *inode, struct file *fp){	struct stk_camera *dev = fp->private_data;	if (dev->owner == fp) {		stk_stop_stream(dev);		stk_free_buffers(dev);		dev->owner = NULL;	}	if(is_present(dev))		usb_autopm_put_interface(dev->interface);	return 0;}static ssize_t v4l_stk_read(struct file *fp, char __user *buf,		size_t count, loff_t *f_pos){	int i;	int ret;	unsigned long flags;	struct stk_sio_buffer *sbuf;	struct stk_camera *dev = fp->private_data;	if (!is_present(dev))		return -EIO;	if (dev->owner && dev->owner != fp)		return -EBUSY;	dev->owner = fp;	if (!is_streaming(dev)) {		if (stk_initialise(dev)			|| stk_allocate_buffers(dev, 3)			|| stk_start_stream(dev))			return -ENOMEM;		spin_lock_irqsave(&dev->spinlock, flags);		for (i = 0; i < dev->n_sbufs; i++) {			list_add_tail(&dev->sio_bufs[i].list, &dev->sio_avail);			dev->sio_bufs[i].v4lbuf.flags = V4L2_BUF_FLAG_QUEUED;		}		spin_unlock_irqrestore(&dev->spinlock, flags);	}	if (*f_pos == 0) {		if (fp->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;	}	if (count + *f_pos > dev->frame_size)		count = dev->frame_size - *f_pos;	spin_lock_irqsave(&dev->spinlock, flags);	if (list_empty(&dev->sio_full)) {		spin_unlock_irqrestore(&dev->spinlock, flags);		STK_ERROR("BUG: No siobufs ready\n");		return 0;	}	sbuf = list_first_entry(&dev->sio_full, struct stk_sio_buffer, list);	spin_unlock_irqrestore(&dev->spinlock, flags);	if (copy_to_user(buf, sbuf->buffer + *f_pos, count))		return -EFAULT;	*f_pos += count;	if (*f_pos >= dev->frame_size) {		*f_pos = 0;		spin_lock_irqsave(&dev->spinlock, flags);		list_move_tail(&sbuf->list, &dev->sio_avail);		spin_unlock_irqrestore(&dev->spinlock, flags);	}	return count;}static unsigned int v4l_stk_poll(struct file *fp, poll_table *wait){	struct stk_camera *dev = fp->private_data;	poll_wait(fp, &dev->wait_frame, wait);	if (!is_present(dev))		return POLLERR;	if (!list_empty(&dev->sio_full))		return (POLLIN | POLLRDNORM);	return 0;}static void stk_v4l_vm_open(struct vm_area_struct *vma){	struct stk_sio_buffer *sbuf = vma->vm_private_data;	sbuf->mapcount++;}static void stk_v4l_vm_close(struct vm_area_struct *vma){	struct stk_sio_buffer *sbuf = vma->vm_private_data;	sbuf->mapcount--;	if (sbuf->mapcount == 0)		sbuf->v4lbuf.flags &= ~V4L2_BUF_FLAG_MAPPED;}static struct vm_operations_struct stk_v4l_vm_ops = {	.open = stk_v4l_vm_open,	.close = stk_v4l_vm_close};static int v4l_stk_mmap(struct file *fp, struct vm_area_struct *vma){	unsigned int i;	int ret;	unsigned long offset = vma->vm_pgoff << PAGE_SHIFT;	struct stk_camera *dev = fp->private_data;	struct stk_sio_buffer *sbuf = NULL;	if (!(vma->vm_flags & VM_WRITE) || !(vma->vm_flags & VM_SHARED))		return -EINVAL;	for (i = 0; i < dev->n_sbufs; i++) {		if (dev->sio_bufs[i].v4lbuf.m.offset == offset) {			sbuf = dev->sio_bufs + i;			break;		}	}	if (sbuf == NULL)		return -EINVAL;	ret = remap_vmalloc_range(vma, sbuf->buffer, 0);	if (ret)		return ret;	vma->vm_flags |= VM_DONTEXPAND;	vma->vm_private_data = sbuf;	vma->vm_ops = &stk_v4l_vm_ops;	sbuf->v4lbuf.flags |= V4L2_BUF_FLAG_MAPPED;	stk_v4l_vm_open(vma);	return 0;}/* v4l ioctl handlers */static int stk_vidioc_querycap(struct file *filp,		void *priv, struct v4l2_capability *cap){	strcpy(cap->driver, "stk");	strcpy(cap->card, "stk");	cap->version = DRIVER_VERSION_NUM;	cap->capabilities = V4L2_CAP_VIDEO_CAPTURE		| V4L2_CAP_READWRITE | V4L2_CAP_STREAMING;	return 0;}static int stk_vidioc_enum_input(struct file *filp,		void *priv, struct v4l2_input *input){	if (input->index != 0)		return -EINVAL;	strcpy(input->name, "Syntek USB Camera");	input->type = V4L2_INPUT_TYPE_CAMERA;	return 0;}static int stk_vidioc_g_input(struct file *filp, void *priv, unsigned int *i){	*i = 0;	return 0;}static int stk_vidioc_s_input(struct file *filp, void *priv, unsigned int i){	if (i != 0)		return -EINVAL;	else		return 0;}/* from vivi.c */static int stk_vidioc_s_std(struct file *filp, void *priv, v4l2_std_id *a){	return 0;}/* List of all V4Lv2 controls supported by the driver */static struct v4l2_queryctrl stk_controls[] = {	{		.id      = V4L2_CID_BRIGHTNESS,		.type    = V4L2_CTRL_TYPE_INTEGER,		.name    = "Brightness",		.minimum = 0,		.maximum = 0xffff,		.step    = 0x0100,		.default_value = 0x6000,	},	/*TODO: get more controls to work */};static int stk_vidioc_queryctrl(struct file *filp,		void *priv, struct v4l2_queryctrl *c){	int i;	int nbr;	nbr = ARRAY_SIZE(stk_controls);	for (i = 0; i < nbr; i++) {		if (stk_controls[i].id == c->id) {			memcpy(c, &stk_controls[i],				sizeof(struct v4l2_queryctrl));			return 0;		}	}	return -EINVAL;}static int stk_vidioc_g_ctrl(struct file *filp,		void *priv, struct v4l2_control *c){	struct stk_camera *dev = priv;	switch (c->id) {	case V4L2_CID_BRIGHTNESS:		c->value = dev->vsettings.brightness;		break;	default:		return -EINVAL;	}	return 0;}static int stk_vidioc_s_ctrl(struct file *filp,		void *priv, struct v4l2_control *c){	struct stk_camera *dev = priv;	switch (c->id) {	case V4L2_CID_BRIGHTNESS:		dev->vsettings.brightness = c->value;		return stk_sensor_set_brightness(dev, c->value >> 8);	default:		return -EINVAL;	}	return 0;}static int stk_vidioc_enum_fmt_vid_cap(struct file *filp,		void *priv, struct v4l2_fmtdesc *fmtd){	fmtd->flags = 0;	switch (fmtd->index) {	case 0:		fmtd->pixelformat = V4L2_PIX_FMT_RGB565;		strcpy(fmtd->description, "r5g6b5");		break;	case 1:		fmtd->pixelformat = V4L2_PIX_FMT_RGB565X;		strcpy(fmtd->description, "r5g6b5BE");		break;	case 2:		fmtd->pixelformat = V4L2_PIX_FMT_UYVY;		strcpy(fmtd->description, "yuv4:2:2");		break;	case 3:		fmtd->pixelformat = V4L2_PIX_FMT_SBGGR8;		strcpy(fmtd->description, "Raw bayer");		break;	case 4:		fmtd->pixelformat = V4L2_PIX_FMT_YUYV;		strcpy(fmtd->description, "yuv4:2:2");		break;	default:		return -EINVAL;	}	return 0;}static struct stk_size {	unsigned w;	unsigned h;	enum stk_mode m;} stk_sizes[] = {	{ .w = 1280, .h = 1024, .m = MODE_SXGA, },	{ .w = 640,  .h = 480,  .m = MODE_VGA,  },	{ .w = 352,  .h = 288,  .m = MODE_CIF,  },	{ .w = 320,  .h = 240,  .m = MODE_QVGA, },	{ .w = 176,  .h = 144,  .m = MODE_QCIF, },};static int stk_vidioc_g_fmt_vid_cap(struct file *filp,		void *priv, struct v4l2_format *f){	struct v4l2_pix_format *pix_format = &f->fmt.pix;	struct stk_camera *dev = priv;	int i;	for (i = 0; i < ARRAY_SIZE(stk_sizes)			&& stk_sizes[i].m != dev->vsettings.mode;		i++);	if (i == ARRAY_SIZE(stk_sizes)) {		STK_ERROR("ERROR: mode invalid\n");		return -EINVAL;	}	pix_format->width = stk_sizes[i].w;	pix_format->height = stk_sizes[i].h;	pix_format->field = V4L2_FIELD_NONE;	pix_format->colorspace = V4L2_COLORSPACE_SRGB;	pix_format->priv = 0;

⌨️ 快捷键说明

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