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

📄 usbvideo.c

📁 基于S3CEB2410平台LINUX操作系统下 USB驱动源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
		info("%s: In use, disconnect pending.", proc);	else		usbvideo_CameraRelease(uvd);	up(&uvd->lock);	info("USB camera disconnected.");	usbvideo_ClientDecModCount(uvd);}/* * usbvideo_CameraRelease() * * This code does final release of uvd_t. This happens * after the device is disconnected -and- all clients * closed their files. * * History: * 27-Jan-2000 Created. */void usbvideo_CameraRelease(uvd_t *uvd){	static const char proc[] = "usbvideo_CameraRelease";	if (uvd == NULL) {		err("%s: Illegal call", proc);		return;	}	video_unregister_device(&uvd->vdev);	if (uvd->debug > 0)		info("%s: Video unregistered.", proc);#if USES_PROC_FS	assert(uvd->handle != NULL);	if (uvd->handle->uses_procfs) {		dbg("%s: Removing /proc/%s/ filesystem entries.", proc, uvd->handle->drvName);		usbvideo_procfs_level2_destroy(uvd);	}#endif	RingQueue_Free(&uvd->dp);	if (VALID_CALLBACK(uvd, userFree))		GET_CALLBACK(uvd, userFree)(uvd);	uvd->uvd_used = 0;	/* This is atomic, no need to take mutex */}/* * usbvideo_find_struct() * * This code searches the array of preallocated (static) structures * and returns index of the first one that isn't in use. Returns -1 * if there are no free structures. * * History: * 27-Jan-2000 Created. */static int usbvideo_find_struct(usbvideo_t *cams){	int u, rv = -1;	if (cams == NULL) {		err("No usbvideo_t handle?");		return -1;	}	down(&cams->lock);	for (u = 0; u < cams->num_cameras; u++) {		uvd_t *uvd = &cams->cam[u];		if (!uvd->uvd_used) /* This one is free */		{			uvd->uvd_used = 1;	/* In use now */			init_MUTEX(&uvd->lock);	/* to 1 == available */			uvd->dev = NULL;			rv = u;			break;		}	}	up(&cams->lock);	return rv;}uvd_t *usbvideo_AllocateDevice(usbvideo_t *cams){	int i, devnum;	uvd_t *uvd = NULL;	if (cams == NULL) {		err("No usbvideo_t handle?");		return NULL;	}	devnum = usbvideo_find_struct(cams);	if (devnum == -1) {		err("IBM USB camera driver: Too many devices!");		return NULL;	}	uvd = &cams->cam[devnum];	dbg("Device entry #%d. at $%p", devnum, uvd);	/* Not relying upon caller we increase module counter ourselves */	usbvideo_ClientIncModCount(uvd);	down(&uvd->lock);	for (i=0; i < USBVIDEO_NUMSBUF; i++) {		uvd->sbuf[i].urb = usb_alloc_urb(FRAMES_PER_DESC);		if (uvd->sbuf[i].urb == NULL) {			err("usb_alloc_urb(%d.) failed.", FRAMES_PER_DESC);			uvd->uvd_used = 0;			uvd = NULL;			goto allocate_done;		}	}	uvd->user=0;	uvd->remove_pending = 0;	uvd->last_error = 0;	RingQueue_Initialize(&uvd->dp);	/* Initialize video device structure */	memset(&uvd->vdev, 0, sizeof(uvd->vdev));	i = sprintf(uvd->vdev.name, "%s USB Camera", cams->drvName);	if (i >= sizeof(uvd->vdev.name)) {		err("Wrote too much into uvd->vdev.name, expect trouble!");	}	uvd->vdev.type = VID_TYPE_CAPTURE;	uvd->vdev.hardware = VID_HARDWARE_CPIA;	uvd->vdev.open = usbvideo_v4l_open;	uvd->vdev.close = usbvideo_v4l_close;	uvd->vdev.read = usbvideo_v4l_read;	uvd->vdev.write = usbvideo_v4l_write;	uvd->vdev.ioctl = usbvideo_v4l_ioctl;	uvd->vdev.mmap = usbvideo_v4l_mmap;	uvd->vdev.initialize = usbvideo_v4l_initialize;	/*	 * The client is free to overwrite those because we	 * return control to the client's probe function right now.	 */allocate_done:	up (&uvd->lock);	usbvideo_ClientDecModCount(uvd);	return uvd;}int usbvideo_RegisterVideoDevice(uvd_t *uvd){	static const char proc[] = "usbvideo_RegisterVideoDevice";	char tmp1[20], tmp2[20];	/* Buffers for printing */	if (uvd == NULL) {		err("%s: Illegal call.", proc);		return -EINVAL;	}	if (uvd->video_endp == 0) {		info("%s: No video endpoint specified; data pump disabled.", proc);	}	if (uvd->paletteBits == 0) {		err("%s: No palettes specified!", proc);		return -EINVAL;	}	if (uvd->defaultPalette == 0) {		info("%s: No default palette!", proc);	}	uvd->max_frame_size = VIDEOSIZE_X(uvd->canvas) *		VIDEOSIZE_Y(uvd->canvas) * V4L_BYTES_PER_PIXEL;	usbvideo_VideosizeToString(tmp1, sizeof(tmp1), uvd->videosize);	usbvideo_VideosizeToString(tmp2, sizeof(tmp2), uvd->canvas);	if (uvd->debug > 0) {		info("%s: iface=%d. endpoint=$%02x paletteBits=$%08lx",		     proc, uvd->iface, uvd->video_endp, uvd->paletteBits);	}	if (video_register_device(&uvd->vdev, VFL_TYPE_GRABBER, video_nr) == -1) {		err("%s: video_register_device failed", proc);		return -EPIPE;	}	if (uvd->debug > 1) {		info("%s: video_register_device() successful", proc);	}	if (uvd->dev == NULL) {		err("%s: uvd->dev == NULL", proc);		return -EINVAL;	}	info("%s on /dev/video%d: canvas=%s videosize=%s",	     (uvd->handle != NULL) ? uvd->handle->drvName : "???",	     uvd->vdev.minor, tmp2, tmp1);#if USES_PROC_FS	assert(uvd->handle != NULL);	if (uvd->handle->uses_procfs) {		if (uvd->debug > 0) {			info("%s: Creating /proc/video/%s/ filesystem entries.",			     proc, uvd->handle->drvName);		}		usbvideo_procfs_level2_create(uvd);	}#endif	usb_inc_dev_use(uvd->dev);	return 0;}/* ******************************************************************** */int usbvideo_v4l_initialize(struct video_device *dev){	return 0;}long usbvideo_v4l_write(struct video_device *dev, const char *buf,			unsigned long count, int noblock){	return -EINVAL;}int usbvideo_v4l_mmap(struct video_device *dev, const char *adr, unsigned long size){	uvd_t *uvd = (uvd_t *) dev;	unsigned long start = (unsigned long) adr;	unsigned long page, pos;	if (!CAMERA_IS_OPERATIONAL(uvd))		return -EFAULT;	if (size > (((2 * uvd->max_frame_size) + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1)))		return -EINVAL;	pos = (unsigned long) uvd->fbuf;	while (size > 0) {		page = usbvideo_kvirt_to_pa(pos);		if (remap_page_range(start, page, PAGE_SIZE, PAGE_SHARED))			return -EAGAIN;		start += PAGE_SIZE;		pos += PAGE_SIZE;		if (size > PAGE_SIZE)			size -= PAGE_SIZE;		else			size = 0;	}	return 0;}/* * usbvideo_v4l_open() * * This is part of Video 4 Linux API. The driver can be opened by one * client only (checks internal counter 'uvdser'). The procedure * then allocates buffers needed for video processing. * * History: * 22-Jan-2000 Rewrote, moved scratch buffer allocation here. Now the *             camera is also initialized here (once per connect), at *             expense of V4L client (it waits on open() call). * 27-Jan-2000 Used USBVIDEO_NUMSBUF as number of URB buffers. * 24-May-2000 Corrected to prevent race condition (MOD_xxx_USE_COUNT). */int usbvideo_v4l_open(struct video_device *dev, int flags){	static const char proc[] = "usbvideo_v4l_open";	uvd_t *uvd = (uvd_t *) dev;	const int sb_size = FRAMES_PER_DESC * uvd->iso_packet_len;	int i, errCode = 0;	if (uvd->debug > 1)		info("%s($%p,$%08x", proc, dev, flags);	usbvideo_ClientIncModCount(uvd);	down(&uvd->lock);	if (uvd->user) {		err("%s: Someone tried to open an already opened device!", proc);		errCode = -EBUSY;	} else {		/* Clear statistics */		memset(&uvd->stats, 0, sizeof(uvd->stats));		/* Clean pointers so we know if we allocated something */		for (i=0; i < USBVIDEO_NUMSBUF; i++)			uvd->sbuf[i].data = NULL;		/* Allocate memory for the frame buffers */		uvd->fbuf_size = USBVIDEO_NUMFRAMES * uvd->max_frame_size;		uvd->fbuf = usbvideo_rvmalloc(uvd->fbuf_size);		RingQueue_Allocate(&uvd->dp, 128*1024); /* FIXME #define */		if ((uvd->fbuf == NULL) ||		    (!RingQueue_IsAllocated(&uvd->dp))) {			err("%s: Failed to allocate fbuf or dp", proc);			errCode = -ENOMEM;		} else {			/* Allocate all buffers */			for (i=0; i < USBVIDEO_NUMFRAMES; i++) {				uvd->frame[i].frameState = FrameState_Unused;				uvd->frame[i].data = uvd->fbuf + i*(uvd->max_frame_size);				/*				 * Set default sizes in case IOCTL (VIDIOCMCAPTURE)				 * is not used (using read() instead).				 */				uvd->frame[i].canvas = uvd->canvas;				uvd->frame[i].seqRead_Index = 0;			}			for (i=0; i < USBVIDEO_NUMSBUF; i++) {				uvd->sbuf[i].data = kmalloc(sb_size, GFP_KERNEL);				if (uvd->sbuf[i].data == NULL) {					errCode = -ENOMEM;					break;				}			}		}		if (errCode != 0) {			/* Have to free all that memory */			if (uvd->fbuf != NULL) {				usbvideo_rvfree(uvd->fbuf, uvd->fbuf_size);				uvd->fbuf = NULL;			}			RingQueue_Free(&uvd->dp);			for (i=0; i < USBVIDEO_NUMSBUF; i++) {				if (uvd->sbuf[i].data != NULL) {					kfree (uvd->sbuf[i].data);					uvd->sbuf[i].data = NULL;				}			}		}	}	/* If so far no errors then we shall start the camera */	if (errCode == 0) {		/* Start data pump if we have valid endpoint */		if (uvd->video_endp != 0)			errCode = usbvideo_StartDataPump(uvd);		if (errCode == 0) {			if (VALID_CALLBACK(uvd, setupOnOpen)) {				if (uvd->debug > 1)					info("%s: setupOnOpen callback", proc);				errCode = GET_CALLBACK(uvd, setupOnOpen)(uvd);				if (errCode < 0) {					err("%s: setupOnOpen callback failed (%d.).",					    proc, errCode);				} else if (uvd->debug > 1) {					info("%s: setupOnOpen callback successful", proc);				}			}			if (errCode == 0) {				uvd->settingsAdjusted = 0;				if (uvd->debug > 1)					info("%s: Open succeeded.", proc);				uvd->user++;			}		}	}	up(&uvd->lock);	if (errCode != 0)		usbvideo_ClientDecModCount(uvd);	if (uvd->debug > 0)		info("%s: Returning %d.", proc, errCode);	return errCode;}/* * usbvideo_v4l_close() * * This is part of Video 4 Linux API. The procedure * stops streaming and deallocates all buffers that were earlier * allocated in usbvideo_v4l_open(). * * History: * 22-Jan-2000 Moved scratch buffer deallocation here. * 27-Jan-2000 Used USBVIDEO_NUMSBUF as number of URB buffers. * 24-May-2000 Moved MOD_DEC_USE_COUNT outside of code that can sleep. */void usbvideo_v4l_close(struct video_device *dev){	static const char proc[] = "usbvideo_v4l_close";	uvd_t *uvd = (uvd_t *)dev;	int i;	if (uvd->debug > 1)		info("%s($%p)", proc, dev);	down(&uvd->lock);		usbvideo_StopDataPump(uvd);	usbvideo_rvfree(uvd->fbuf, uvd->fbuf_size);	uvd->fbuf = NULL;	RingQueue_Free(&uvd->dp);	for (i=0; i < USBVIDEO_NUMSBUF; i++) {		kfree(uvd->sbuf[i].data);		uvd->sbuf[i].data = NULL;	}#if USBVIDEO_REPORT_STATS	usbvideo_ReportStatistics(uvd);#endif    	uvd->user--;	if (uvd->remove_pending) {		if (uvd->debug > 0)			info("usbvideo_v4l_close: Final disconnect.");		usbvideo_CameraRelease(uvd);	}	up(&uvd->lock);	usbvideo_ClientDecModCount(uvd);	if (uvd->debug > 1)		info("%s: Completed.", proc);}/* * usbvideo_v4l_ioctl() * * This is part of Video 4 Linux API. The procedure handles ioctl() calls. * * History: * 22-Jan-2000 Corrected VIDIOCSPICT to reject unsupported settings. */int usbvideo_v4l_ioctl(struct video_device *dev, unsigned int cmd, void *arg){	uvd_t *uvd = (uvd_t *)dev;	if (!CAMERA_IS_OPERATIONAL(uvd))		return -EFAULT;	switch (cmd) {		case VIDIOCGCAP:		{			if (copy_to_user(arg, &uvd->vcap, sizeof(uvd->vcap)))				return -EFAULT;			return 0;		}		case VIDIOCGCHAN:		{			if (copy_to_user(arg, &uvd->vchan, sizeof(uvd->vchan)))				return -EFAULT;			return 0;		}		case VIDIOCSCHAN:		{	/* Not used but we return success */			int v;			if (copy_from_user(&v, arg, sizeof(v)))				return -EFAULT;			return 0;		}		case VIDIOCGPICT:		{			if (copy_to_user(arg, &uvd->vpic, sizeof(uvd->vpic)))				return -EFAULT;			return 0;		}		case VIDIOCSPICT:		{			struct video_picture tmp;			/*			 * Use temporary 'video_picture' structure to preserve our			 * own settings (such as color depth, palette) that we			 * aren't allowing everyone (V4L client) to change.			 */			if (copy_from_user(&tmp, arg, sizeof(tmp)))				return -EFAULT;			uvd->vpic.brightness = tmp.brightness;			uvd->vpic.hue = tmp.hue;			uvd->vpic.colour = tmp.colour;			uvd->vpic.contrast = tmp.contrast;			uvd->settingsAdjusted = 0;	/* Will force new settings */			return 0;		}		case VIDIOCSWIN:		{			struct video_window vw;			if (copy_from_user(&vw, arg, sizeof(vw)))				return -EFAULT;			if (vw.flags)				return -EINVAL;			if (vw.clipcount)				return -EINVAL;			if (vw.width != VIDEOSIZE_X(uvd->canvas))				return -EINVAL;			if (vw.height != VIDEOSIZE_Y(uvd->canvas))				return -EINVAL;			return 0;		}		case VIDIOCGWIN:		{			struct video_window vw;			vw.x = 0;			vw.y = 0;			vw.width = VIDEOSIZE_X(uvd->canvas);

⌨️ 快捷键说明

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