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

📄 sn9c102_core.c

📁 V4l driver for DVB HD
💻 C
📖 第 1 页 / 共 5 页
字号:
	spin_unlock_irqrestore(&cam->queue_lock, lock_flags);	sn9c102_queue_unusedframes(cam);	PDBGG("Frame #%lu, bytes read: %zu",	      (unsigned long)f->buf.index, count);	mutex_unlock(&cam->fileop_mutex);	return count;}static unsigned int sn9c102_poll(struct file *filp, poll_table *wait){	struct sn9c102_device* cam = video_get_drvdata(video_devdata(filp));	struct sn9c102_frame_t* f;	unsigned long lock_flags;	unsigned int mask = 0;	if (mutex_lock_interruptible(&cam->fileop_mutex))		return POLLERR;	if (cam->state & DEV_DISCONNECTED) {		DBG(1, "Device not present");		goto error;	}	if (cam->state & DEV_MISCONFIGURED) {		DBG(1, "The camera is misconfigured. Close and open it "		       "again.");		goto error;	}	if (cam->io == IO_NONE) {		if (!sn9c102_request_buffers(cam, cam->nreadbuffers,					     IO_READ)) {			DBG(1, "poll() failed, not enough memory");			goto error;		}		cam->io = IO_READ;		cam->stream = STREAM_ON;	}	if (cam->io == IO_READ) {		spin_lock_irqsave(&cam->queue_lock, lock_flags);		list_for_each_entry(f, &cam->outqueue, frame)			f->state = F_UNUSED;		INIT_LIST_HEAD(&cam->outqueue);		spin_unlock_irqrestore(&cam->queue_lock, lock_flags);		sn9c102_queue_unusedframes(cam);	}	poll_wait(filp, &cam->wait_frame, wait);	if (!list_empty(&cam->outqueue))		mask |= POLLIN | POLLRDNORM;	mutex_unlock(&cam->fileop_mutex);	return mask;error:	mutex_unlock(&cam->fileop_mutex);	return POLLERR;}static void sn9c102_vm_open(struct vm_area_struct* vma){	struct sn9c102_frame_t* f = vma->vm_private_data;	f->vma_use_count++;}static void sn9c102_vm_close(struct vm_area_struct* vma){	/* NOTE: buffers are not freed here */	struct sn9c102_frame_t* f = vma->vm_private_data;	f->vma_use_count--;}static struct vm_operations_struct sn9c102_vm_ops = {	.open = sn9c102_vm_open,	.close = sn9c102_vm_close,};static int sn9c102_mmap(struct file* filp, struct vm_area_struct *vma){	struct sn9c102_device* cam = video_get_drvdata(video_devdata(filp));	unsigned long size = vma->vm_end - vma->vm_start,		      start = vma->vm_start;	void *pos;	u32 i;	if (mutex_lock_interruptible(&cam->fileop_mutex))		return -ERESTARTSYS;	if (cam->state & DEV_DISCONNECTED) {		DBG(1, "Device not present");		mutex_unlock(&cam->fileop_mutex);		return -ENODEV;	}	if (cam->state & DEV_MISCONFIGURED) {		DBG(1, "The camera is misconfigured. Close and open it "		       "again.");		mutex_unlock(&cam->fileop_mutex);		return -EIO;	}	if (cam->io != IO_MMAP || !(vma->vm_flags & VM_WRITE) ||	    size != PAGE_ALIGN(cam->frame[0].buf.length)) {		mutex_unlock(&cam->fileop_mutex);		return -EINVAL;	}	for (i = 0; i < cam->nbuffers; i++) {		if ((cam->frame[i].buf.m.offset>>PAGE_SHIFT) == vma->vm_pgoff)			break;	}	if (i == cam->nbuffers) {		mutex_unlock(&cam->fileop_mutex);		return -EINVAL;	}	vma->vm_flags |= VM_IO;	vma->vm_flags |= VM_RESERVED;	pos = cam->frame[i].bufmem;	while (size > 0) { /* size is page-aligned */		if (vm_insert_page(vma, start, vmalloc_to_page(pos))) {			mutex_unlock(&cam->fileop_mutex);			return -EAGAIN;		}		start += PAGE_SIZE;		pos += PAGE_SIZE;		size -= PAGE_SIZE;	}	vma->vm_ops = &sn9c102_vm_ops;	vma->vm_private_data = &cam->frame[i];	sn9c102_vm_open(vma);	mutex_unlock(&cam->fileop_mutex);	return 0;}/*****************************************************************************/static intsn9c102_vidioc_querycap(struct sn9c102_device* cam, void __user * arg){	struct v4l2_capability cap = {		.driver = "sn9c102",		.version = SN9C102_MODULE_VERSION_CODE,		.capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_READWRITE |				V4L2_CAP_STREAMING,	};	strlcpy(cap.card, cam->v4ldev->name, sizeof(cap.card));	if (usb_make_path(cam->usbdev, cap.bus_info, sizeof(cap.bus_info)) < 0)		strlcpy(cap.bus_info, cam->usbdev->dev.bus_id,			sizeof(cap.bus_info));	if (copy_to_user(arg, &cap, sizeof(cap)))		return -EFAULT;	return 0;}static intsn9c102_vidioc_enuminput(struct sn9c102_device* cam, void __user * arg){	struct v4l2_input i;	if (copy_from_user(&i, arg, sizeof(i)))		return -EFAULT;	if (i.index)		return -EINVAL;	memset(&i, 0, sizeof(i));	strcpy(i.name, "Camera");	i.type = V4L2_INPUT_TYPE_CAMERA;	if (copy_to_user(arg, &i, sizeof(i)))		return -EFAULT;	return 0;}static intsn9c102_vidioc_g_input(struct sn9c102_device* cam, void __user * arg){	int index = 0;	if (copy_to_user(arg, &index, sizeof(index)))		return -EFAULT;	return 0;}static intsn9c102_vidioc_s_input(struct sn9c102_device* cam, void __user * arg){	int index;	if (copy_from_user(&index, arg, sizeof(index)))		return -EFAULT;	if (index != 0)		return -EINVAL;	return 0;}static intsn9c102_vidioc_query_ctrl(struct sn9c102_device* cam, void __user * arg){	struct sn9c102_sensor* s = &cam->sensor;	struct v4l2_queryctrl qc;	u8 i;	if (copy_from_user(&qc, arg, sizeof(qc)))		return -EFAULT;	for (i = 0; i < ARRAY_SIZE(s->qctrl); i++)		if (qc.id && qc.id == s->qctrl[i].id) {			memcpy(&qc, &(s->qctrl[i]), sizeof(qc));			if (copy_to_user(arg, &qc, sizeof(qc)))				return -EFAULT;			return 0;		}	return -EINVAL;}static intsn9c102_vidioc_g_ctrl(struct sn9c102_device* cam, void __user * arg){	struct sn9c102_sensor* s = &cam->sensor;	struct v4l2_control ctrl;	int err = 0;	u8 i;	if (!s->get_ctrl && !s->set_ctrl)		return -EINVAL;	if (copy_from_user(&ctrl, arg, sizeof(ctrl)))		return -EFAULT;	if (!s->get_ctrl) {		for (i = 0; i < ARRAY_SIZE(s->qctrl); i++)			if (ctrl.id && ctrl.id == s->qctrl[i].id) {				ctrl.value = s->_qctrl[i].default_value;				goto exit;			}		return -EINVAL;	} else		err = s->get_ctrl(cam, &ctrl);exit:	if (copy_to_user(arg, &ctrl, sizeof(ctrl)))		return -EFAULT;	return err;}static intsn9c102_vidioc_s_ctrl(struct sn9c102_device* cam, void __user * arg){	struct sn9c102_sensor* s = &cam->sensor;	struct v4l2_control ctrl;	u8 i;	int err = 0;	if (!s->set_ctrl)		return -EINVAL;	if (copy_from_user(&ctrl, arg, sizeof(ctrl)))		return -EFAULT;	for (i = 0; i < ARRAY_SIZE(s->qctrl); i++)		if (ctrl.id == s->qctrl[i].id) {			if (s->qctrl[i].flags & V4L2_CTRL_FLAG_DISABLED)				return -EINVAL;			if (ctrl.value < s->qctrl[i].minimum ||			    ctrl.value > s->qctrl[i].maximum)				return -ERANGE;			ctrl.value -= ctrl.value % s->qctrl[i].step;			break;		}	if ((err = s->set_ctrl(cam, &ctrl)))		return err;	s->_qctrl[i].default_value = ctrl.value;	PDBGG("VIDIOC_S_CTRL: id %lu, value %lu",	      (unsigned long)ctrl.id, (unsigned long)ctrl.value);	return 0;}static intsn9c102_vidioc_cropcap(struct sn9c102_device* cam, void __user * arg){	struct v4l2_cropcap* cc = &(cam->sensor.cropcap);	cc->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;	cc->pixelaspect.numerator = 1;	cc->pixelaspect.denominator = 1;	if (copy_to_user(arg, cc, sizeof(*cc)))		return -EFAULT;	return 0;}static intsn9c102_vidioc_g_crop(struct sn9c102_device* cam, void __user * arg){	struct sn9c102_sensor* s = &cam->sensor;	struct v4l2_crop crop = {		.type = V4L2_BUF_TYPE_VIDEO_CAPTURE,	};	memcpy(&(crop.c), &(s->_rect), sizeof(struct v4l2_rect));	if (copy_to_user(arg, &crop, sizeof(crop)))		return -EFAULT;	return 0;}static intsn9c102_vidioc_s_crop(struct sn9c102_device* cam, void __user * arg){	struct sn9c102_sensor* s = &cam->sensor;	struct v4l2_crop crop;	struct v4l2_rect* rect;	struct v4l2_rect* bounds = &(s->cropcap.bounds);	struct v4l2_pix_format* pix_format = &(s->pix_format);	u8 scale;	const enum sn9c102_stream_state stream = cam->stream;	const u32 nbuffers = cam->nbuffers;	u32 i;	int err = 0;	if (copy_from_user(&crop, arg, sizeof(crop)))		return -EFAULT;	rect = &(crop.c);	if (crop.type != V4L2_BUF_TYPE_VIDEO_CAPTURE)		return -EINVAL;	if (cam->module_param.force_munmap)		for (i = 0; i < cam->nbuffers; i++)			if (cam->frame[i].vma_use_count) {				DBG(3, "VIDIOC_S_CROP failed. "				       "Unmap the buffers first.");				return -EINVAL;			}	/* Preserve R,G or B origin */	rect->left = (s->_rect.left & 1L) ? rect->left | 1L : rect->left & ~1L;	rect->top = (s->_rect.top & 1L) ? rect->top | 1L : rect->top & ~1L;	if (rect->width < 16)		rect->width = 16;	if (rect->height < 16)		rect->height = 16;	if (rect->width > bounds->width)		rect->width = bounds->width;	if (rect->height > bounds->height)		rect->height = bounds->height;	if (rect->left < bounds->left)		rect->left = bounds->left;	if (rect->top < bounds->top)		rect->top = bounds->top;	if (rect->left + rect->width > bounds->left + bounds->width)		rect->left = bounds->left+bounds->width - rect->width;	if (rect->top + rect->height > bounds->top + bounds->height)		rect->top = bounds->top+bounds->height - rect->height;	rect->width &= ~15L;	rect->height &= ~15L;	if (SN9C102_PRESERVE_IMGSCALE) {		/* Calculate the actual scaling factor */		u32 a, b;		a = rect->width * rect->height;		b = pix_format->width * pix_format->height;		scale = b ? (u8)((a / b) < 4 ? 1 : ((a / b) < 16 ? 2 : 4)) : 1;	} else		scale = 1;	if (cam->stream == STREAM_ON)		if ((err = sn9c102_stream_interrupt(cam)))			return err;	if (copy_to_user(arg, &crop, sizeof(crop))) {		cam->stream = stream;		return -EFAULT;	}	if (cam->module_param.force_munmap || cam->io == IO_READ)		sn9c102_release_buffers(cam);	err = sn9c102_set_crop(cam, rect);	if (s->set_crop)		err += s->set_crop(cam, rect);	err += sn9c102_set_scale(cam, scale);	if (err) { /* atomic, no rollback in ioctl() */		cam->state |= DEV_MISCONFIGURED;		DBG(1, "VIDIOC_S_CROP failed because of hardware problems. To "		       "use the camera, close and open /dev/video%d again.",		    cam->v4ldev->minor);		return -EIO;	}	s->pix_format.width = rect->width/scale;	s->pix_format.height = rect->height/scale;	memcpy(&(s->_rect), rect, sizeof(*rect));	if ((cam->module_param.force_munmap || cam->io == IO_READ) &&	    nbuffers != sn9c102_request_buffers(cam, nbuffers, cam->io)) {		cam->state |= DEV_MISCONFIGURED;		DBG(1, "VIDIOC_S_CROP failed because of not enough memory. To "		       "use the camera, close and open /dev/video%d again.",		    cam->v4ldev->minor);		return -ENOMEM;	}	if (cam->io == IO_READ)		sn9c102_empty_framequeues(cam);	else if (cam->module_param.force_munmap)		sn9c102_requeue_outqueue(cam);	cam->stream = stream;	return 0;}static intsn9c102_vidioc_enum_fmt(struct sn9c102_device* cam, void __user * arg){	struct v4l2_fmtdesc fmtd;	if (copy_from_user(&fmtd, arg, sizeof(fmtd)))		return -EFAULT;	if (fmtd.index == 0) {		strcpy(fmtd.description, "bayer rgb");		fmtd.pixelformat = V4L2_PIX_FMT_SBGGR8;	} else if (fmtd.index == 1) {		strcpy(fmtd.description, "compressed");		fmtd.pixelformat = V4L2_PIX_FMT_SN9C10X;		fmtd.flags = V4L2_FMT_FLAG_COMPRESSED;	} else		return -EINVAL;	fmtd.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;	memset(&fmtd.reserved, 0, sizeof(fmtd.reserved));	if (copy_to_user(arg, &fmtd, sizeof(fmtd)))		return -EFAULT;	return 0;}static intsn9c102_vidioc_g_fmt(struct sn9c102_device* cam, void __user * arg){	struct v4l2_format format;	struct v4l2_pix_format* pfmt = &(cam->sensor.pix_format);	if (copy_from_user(&format, arg, sizeof(format)))		return -EFAULT;	if (format.type != V4L2_BUF_TYPE_VIDEO_CAPTURE)		return -EINVAL;	pfmt->bytesperline = (pfmt->pixelformat==V4L2_PIX_FMT_SN9C10X)			     ? 0 : (pfmt->width * pfmt->priv) / 8;	pfmt->sizeimage = pfmt->height * ((pfmt->width*pfmt->priv)/8);	pfmt->field = V4L2_FIELD_NONE;	memcpy(&(format.fmt.pix), pfmt, sizeof(*pfmt));	if (copy_to_user(arg, &format, sizeof(format)))		return -EFAULT;	return 0;}static intsn9c102_vidioc_try_s_fmt(struct sn9c102_device* cam, unsigned int cmd,			 void __user * arg){	struct sn9c102_sensor* s = &cam->sensor;	struct v4l2_format format;	struct v4l2_pix_format* pix;	struct v4l2_pix_format* pfmt = &(s->pix_format);	struct v4l2_rect* bounds = &(s->cropcap.bounds);	struct v4l2_rect rect;	u8 scale;	const enum sn9c102_stream_state stream = cam->stream;	const u32 nbuffers = cam->nbuffers;	u32 i;	int err = 0;	if (copy_from_user(&format, arg, sizeof(format)))		return -EFAULT;	pix = &(format.fmt.pix);	if (format.type != V4L2_BUF_TYPE_VIDEO_CAPTURE)		return -EINVAL;	memcpy(&rect, &(s->_rect), sizeof(rect));	{ /* calculate the actual scaling factor */		u32 a, b;		a = rect.width * rect.height;		b = pix->width * pix->height;		scale = b ? (u8)((a / b) < 4 ? 1 : ((a / b) < 16 ? 2 : 4)) : 1;	}

⌨️ 快捷键说明

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