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

📄 vicam.c

📁 linux内核源码
💻 C
📖 第 1 页 / 共 3 页
字号:
	/* guard against simultaneous accesses to the camera */	struct mutex cam_lock;	int is_initialized;	u8 open_count;	u8 bulkEndpoint;	int needsDummyRead;};static int vicam_probe( struct usb_interface *intf, const struct usb_device_id *id);static void vicam_disconnect(struct usb_interface *intf);static void read_frame(struct vicam_camera *cam, int framenum);static void vicam_decode_color(const u8 *, u8 *);static int __send_control_msg(struct vicam_camera *cam,			      u8 request,			      u16 value,			      u16 index,			      unsigned char *cp,			      u16 size){	int status;	/* cp must be memory that has been allocated by kmalloc */	status = usb_control_msg(cam->udev,				 usb_sndctrlpipe(cam->udev, 0),				 request,				 USB_DIR_OUT | USB_TYPE_VENDOR |				 USB_RECIP_DEVICE, value, index,				 cp, size, 1000);	status = min(status, 0);	if (status < 0) {		printk(KERN_INFO "Failed sending control message, error %d.\n",		       status);	}	return status;}static int send_control_msg(struct vicam_camera *cam,			    u8 request,			    u16 value,			    u16 index,			    unsigned char *cp,			    u16 size){	int status = -ENODEV;	mutex_lock(&cam->cam_lock);	if (cam->udev) {		status = __send_control_msg(cam, request, value,					    index, cp, size);	}	mutex_unlock(&cam->cam_lock);	return status;}static intinitialize_camera(struct vicam_camera *cam){	const struct {		u8 *data;		u32 size;	} firmware[] = {		{ .data = setup1, .size = sizeof(setup1) },		{ .data = setup2, .size = sizeof(setup2) },		{ .data = setup3, .size = sizeof(setup3) },		{ .data = setup4, .size = sizeof(setup4) },		{ .data = setup5, .size = sizeof(setup5) },		{ .data = setup3, .size = sizeof(setup3) },		{ .data = NULL, .size = 0 }	};	int err, i;	for (i = 0, err = 0; firmware[i].data && !err; i++) {		memcpy(cam->cntrlbuf, firmware[i].data, firmware[i].size);		err = send_control_msg(cam, 0xff, 0, 0,				       cam->cntrlbuf, firmware[i].size);	}	return err;}static intset_camera_power(struct vicam_camera *cam, int state){	int status;	if ((status = send_control_msg(cam, 0x50, state, 0, NULL, 0)) < 0)		return status;	if (state) {		send_control_msg(cam, 0x55, 1, 0, NULL, 0);	}	return 0;}static intvicam_ioctl(struct inode *inode, struct file *file, unsigned int ioctlnr, unsigned long arg){	void __user *user_arg = (void __user *)arg;	struct vicam_camera *cam = file->private_data;	int retval = 0;	if (!cam)		return -ENODEV;	switch (ioctlnr) {		/* query capabilities */	case VIDIOCGCAP:		{			struct video_capability b;			DBG("VIDIOCGCAP\n");			memset(&b, 0, sizeof(b));			strcpy(b.name, "ViCam-based Camera");			b.type = VID_TYPE_CAPTURE;			b.channels = 1;			b.audios = 0;			b.maxwidth = 320;	/* VIDEOSIZE_CIF */			b.maxheight = 240;			b.minwidth = 320;	/* VIDEOSIZE_48_48 */			b.minheight = 240;			if (copy_to_user(user_arg, &b, sizeof(b)))				retval = -EFAULT;			break;		}		/* get/set video source - we are a camera and nothing else */	case VIDIOCGCHAN:		{			struct video_channel v;			DBG("VIDIOCGCHAN\n");			if (copy_from_user(&v, user_arg, sizeof(v))) {				retval = -EFAULT;				break;			}			if (v.channel != 0) {				retval = -EINVAL;				break;			}			v.channel = 0;			strcpy(v.name, "Camera");			v.tuners = 0;			v.flags = 0;			v.type = VIDEO_TYPE_CAMERA;			v.norm = 0;			if (copy_to_user(user_arg, &v, sizeof(v)))				retval = -EFAULT;			break;		}	case VIDIOCSCHAN:		{			int v;			if (copy_from_user(&v, user_arg, sizeof(v)))				retval = -EFAULT;			DBG("VIDIOCSCHAN %d\n", v);			if (retval == 0 && v != 0)				retval = -EINVAL;			break;		}		/* image properties */	case VIDIOCGPICT:		{			struct video_picture vp;			DBG("VIDIOCGPICT\n");			memset(&vp, 0, sizeof (struct video_picture));			vp.brightness = cam->gain << 8;			vp.depth = 24;			vp.palette = VIDEO_PALETTE_RGB24;			if (copy_to_user(user_arg, &vp, sizeof (struct video_picture)))				retval = -EFAULT;			break;		}	case VIDIOCSPICT:		{			struct video_picture vp;			if (copy_from_user(&vp, user_arg, sizeof(vp))) {				retval = -EFAULT;				break;			}			DBG("VIDIOCSPICT depth = %d, pal = %d\n", vp.depth,			    vp.palette);			cam->gain = vp.brightness >> 8;			if (vp.depth != 24			    || vp.palette != VIDEO_PALETTE_RGB24)				retval = -EINVAL;			break;		}		/* get/set capture window */	case VIDIOCGWIN:		{			struct video_window vw;			vw.x = 0;			vw.y = 0;			vw.width = 320;			vw.height = 240;			vw.chromakey = 0;			vw.flags = 0;			vw.clips = NULL;			vw.clipcount = 0;			DBG("VIDIOCGWIN\n");			if (copy_to_user(user_arg, (void *)&vw, sizeof(vw)))				retval = -EFAULT;			// I'm not sure what the deal with a capture window is, it is very poorly described			// in the doc.  So I won't support it now.			break;		}	case VIDIOCSWIN:		{			struct video_window vw;			if (copy_from_user(&vw, user_arg, sizeof(vw))) {				retval = -EFAULT;				break;			}			DBG("VIDIOCSWIN %d x %d\n", vw.width, vw.height);			if ( vw.width != 320 || vw.height != 240 )				retval = -EFAULT;			break;		}		/* mmap interface */	case VIDIOCGMBUF:		{			struct video_mbuf vm;			int i;			DBG("VIDIOCGMBUF\n");			memset(&vm, 0, sizeof (vm));			vm.size =			    VICAM_MAX_FRAME_SIZE * VICAM_FRAMES;			vm.frames = VICAM_FRAMES;			for (i = 0; i < VICAM_FRAMES; i++)				vm.offsets[i] = VICAM_MAX_FRAME_SIZE * i;			if (copy_to_user(user_arg, (void *)&vm, sizeof(vm)))				retval = -EFAULT;			break;		}	case VIDIOCMCAPTURE:		{			struct video_mmap vm;			// int video_size;			if (copy_from_user((void *)&vm, user_arg, sizeof(vm))) {				retval = -EFAULT;				break;			}			DBG("VIDIOCMCAPTURE frame=%d, height=%d, width=%d, format=%d.\n",vm.frame,vm.width,vm.height,vm.format);			if ( vm.frame >= VICAM_FRAMES || vm.format != VIDEO_PALETTE_RGB24 )				retval = -EINVAL;			// in theory right here we'd start the image capturing			// (fill in a bulk urb and submit it asynchronously)			//			// Instead we're going to do a total hack job for now and			// retrieve the frame in VIDIOCSYNC			break;		}	case VIDIOCSYNC:		{			int frame;			if (copy_from_user((void *)&frame, user_arg, sizeof(int))) {				retval = -EFAULT;				break;			}			DBG("VIDIOCSYNC: %d\n", frame);			read_frame(cam, frame);			vicam_decode_color(cam->raw_image,					   cam->framebuf +					   frame * VICAM_MAX_FRAME_SIZE );			break;		}		/* pointless to implement overlay with this camera */	case VIDIOCCAPTURE:	case VIDIOCGFBUF:	case VIDIOCSFBUF:	case VIDIOCKEY:		retval = -EINVAL;		break;		/* tuner interface - we have none */	case VIDIOCGTUNER:	case VIDIOCSTUNER:	case VIDIOCGFREQ:	case VIDIOCSFREQ:		retval = -EINVAL;		break;		/* audio interface - we have none */	case VIDIOCGAUDIO:	case VIDIOCSAUDIO:		retval = -EINVAL;		break;	default:		retval = -ENOIOCTLCMD;		break;	}	return retval;}static intvicam_open(struct inode *inode, struct file *file){	struct video_device *dev = video_devdata(file);	struct vicam_camera *cam =	    (struct vicam_camera *) dev->priv;	DBG("open\n");	if (!cam) {		printk(KERN_ERR		       "vicam video_device improperly initialized");		return -EINVAL;	}	/* the videodev_lock held above us protects us from	 * simultaneous opens...for now. we probably shouldn't	 * rely on this fact forever.	 */	if (cam->open_count > 0) {		printk(KERN_INFO		       "vicam_open called on already opened camera");		return -EBUSY;	}	cam->raw_image = kmalloc(VICAM_MAX_READ_SIZE, GFP_KERNEL);	if (!cam->raw_image) {		return -ENOMEM;	}	cam->framebuf = rvmalloc(VICAM_MAX_FRAME_SIZE * VICAM_FRAMES);	if (!cam->framebuf) {		kfree(cam->raw_image);		return -ENOMEM;	}	cam->cntrlbuf = kmalloc(PAGE_SIZE, GFP_KERNEL);	if (!cam->cntrlbuf) {		kfree(cam->raw_image);		rvfree(cam->framebuf, VICAM_MAX_FRAME_SIZE * VICAM_FRAMES);		return -ENOMEM;	}	// First upload firmware, then turn the camera on	if (!cam->is_initialized) {		initialize_camera(cam);		cam->is_initialized = 1;	}	set_camera_power(cam, 1);	cam->needsDummyRead = 1;	cam->open_count++;	file->private_data = cam;	return 0;}static intvicam_close(struct inode *inode, struct file *file){	struct vicam_camera *cam = file->private_data;	int open_count;	struct usb_device *udev;	DBG("close\n");

⌨️ 快捷键说明

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