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

📄 usbvideo.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 4 页
字号:
		info("testpattern: frame=%s", tmp);	}#endif	/* Form every scan line */	for (; frame->curline < VIDEOSIZE_Y(frame->request); frame->curline++) {		int i;		unsigned char *f = frame->data +			(VIDEOSIZE_X(frame->request) * V4L_BYTES_PER_PIXEL * frame->curline);		for (i=0; i < VIDEOSIZE_X(frame->request); i++) {			unsigned char cb=0x80;			unsigned char cg = 0;			unsigned char cr = 0;			if (pmode == 1) {				if (frame->curline % 32 == 0)					cb = 0, cg = cr = 0xFF;				else if (i % 32 == 0) {					if (frame->curline % 32 == 1)						num_cell++;					cb = 0, cg = cr = 0xFF;				} else {					cb = ((num_cell*7) + num_pass) & 0xFF;					cg = ((num_cell*5) + num_pass*2) & 0xFF;					cr = ((num_cell*3) + num_pass*3) & 0xFF;				}			} else {				/* Just the blue screen */			}							*f++ = cb;			*f++ = cg;			*f++ = cr;			scan_length += 3;		}	}	frame->frameState = FrameState_Done;	frame->seqRead_Length += scan_length;	++num_pass;	/* We do this unconditionally, regardless of FLAGS_OVERLAY_STATS */	usbvideo_OverlayStats(uvd, frame);}EXPORT_SYMBOL(usbvideo_TestPattern);#ifdef DEBUG/* * usbvideo_HexDump() * * A debugging tool. Prints hex dumps. * * History: * 29-Jul-2000 Added printing of offsets. */void usbvideo_HexDump(const unsigned char *data, int len){	const int bytes_per_line = 32;	char tmp[128]; /* 32*3 + 5 */	int i, k;	for (i=k=0; len > 0; i++, len--) {		if (i > 0 && ((i % bytes_per_line) == 0)) {			printk("%s\n", tmp);			k=0;		}		if ((i % bytes_per_line) == 0)			k += sprintf(&tmp[k], "%04x: ", i);		k += sprintf(&tmp[k], "%02x ", data[i]);	}	if (k > 0)		printk("%s\n", tmp);}EXPORT_SYMBOL(usbvideo_HexDump);#endif/* ******************************************************************** *//* XXX: this piece of crap really wants some error handling.. */static void usbvideo_ClientIncModCount(struct uvd *uvd){	if (uvd == NULL) {		err("%s: uvd == NULL", __FUNCTION__);		return;	}	if (uvd->handle == NULL) {		err("%s: uvd->handle == NULL", __FUNCTION__);		return;	}	if (uvd->handle->md_module == NULL) {		err("%s: uvd->handle->md_module == NULL", __FUNCTION__);		return;	}	if (!try_module_get(uvd->handle->md_module)) {		err("%s: try_module_get() == 0", __FUNCTION__);		return;	}}static void usbvideo_ClientDecModCount(struct uvd *uvd){	if (uvd == NULL) {		err("%s: uvd == NULL", __FUNCTION__);		return;	}	if (uvd->handle == NULL) {		err("%s: uvd->handle == NULL", __FUNCTION__);		return;	}	if (uvd->handle->md_module == NULL) {		err("%s: uvd->handle->md_module == NULL", __FUNCTION__);		return;	}	module_put(uvd->handle->md_module);}int usbvideo_register(	struct usbvideo **pCams,	const int num_cams,	const int num_extra,	const char *driverName,	const struct usbvideo_cb *cbTbl,	struct module *md,	const struct usb_device_id *id_table){	struct usbvideo *cams;	int i, base_size, result;	/* Check parameters for sanity */	if ((num_cams <= 0) || (pCams == NULL) || (cbTbl == NULL)) {		err("%s: Illegal call", __FUNCTION__);		return -EINVAL;	}	/* Check registration callback - must be set! */	if (cbTbl->probe == NULL) {		err("%s: probe() is required!", __FUNCTION__);		return -EINVAL;	}	base_size = num_cams * sizeof(struct uvd) + sizeof(struct usbvideo);	cams = (struct usbvideo *) kmalloc(base_size, GFP_KERNEL);	if (cams == NULL) {		err("Failed to allocate %d. bytes for usbvideo struct", base_size);		return -ENOMEM;	}	dbg("%s: Allocated $%p (%d. bytes) for %d. cameras",	    __FUNCTION__, cams, base_size, num_cams);	memset(cams, 0, base_size);	/* Copy callbacks, apply defaults for those that are not set */	memmove(&cams->cb, cbTbl, sizeof(cams->cb));	if (cams->cb.getFrame == NULL)		cams->cb.getFrame = usbvideo_GetFrame;	if (cams->cb.disconnect == NULL)		cams->cb.disconnect = usbvideo_Disconnect;	if (cams->cb.startDataPump == NULL)		cams->cb.startDataPump = usbvideo_StartDataPump;	if (cams->cb.stopDataPump == NULL)		cams->cb.stopDataPump = usbvideo_StopDataPump;	cams->num_cameras = num_cams;	cams->cam = (struct uvd *) &cams[1];	cams->md_module = md;	if (cams->md_module == NULL)		warn("%s: module == NULL!", __FUNCTION__);	init_MUTEX(&cams->lock);	/* to 1 == available */	for (i = 0; i < num_cams; i++) {		struct uvd *up = &cams->cam[i];		up->handle = cams;		/* Allocate user_data separately because of kmalloc's limits */		if (num_extra > 0) {			up->user_size = num_cams * num_extra;			up->user_data = (char *) kmalloc(up->user_size, GFP_KERNEL);			if (up->user_data == NULL) {				err("%s: Failed to allocate user_data (%d. bytes)",				    __FUNCTION__, up->user_size);				while (i) {					up = &cams->cam[--i];					kfree(up->user_data);				}				kfree(cams);				return -ENOMEM;			}			dbg("%s: Allocated cams[%d].user_data=$%p (%d. bytes)",			     __FUNCTION__, i, up->user_data, up->user_size);		}	}	/*	 * Register ourselves with USB stack.	 */	strcpy(cams->drvName, (driverName != NULL) ? driverName : "Unknown");	cams->usbdrv.name = cams->drvName;	cams->usbdrv.probe = cams->cb.probe;	cams->usbdrv.disconnect = cams->cb.disconnect;	cams->usbdrv.id_table = id_table;	/*	 * Update global handle to usbvideo. This is very important	 * because probe() can be called before usb_register() returns.	 * If the handle is not yet updated then the probe() will fail.	 */	*pCams = cams;	result = usb_register(&cams->usbdrv);	if (result) {		for (i = 0; i < num_cams; i++) {			struct uvd *up = &cams->cam[i];			kfree(up->user_data);		}		kfree(cams);	}	return result;}EXPORT_SYMBOL(usbvideo_register);/* * usbvideo_Deregister() * * Procedure frees all usbvideo and user data structures. Be warned that * if you had some dynamically allocated components in ->user field then * you should free them before calling here. */void usbvideo_Deregister(struct usbvideo **pCams){	struct usbvideo *cams;	int i;	if (pCams == NULL) {		err("%s: pCams == NULL", __FUNCTION__);		return;	}	cams = *pCams;	if (cams == NULL) {		err("%s: cams == NULL", __FUNCTION__);		return;	}	dbg("%s: Deregistering %s driver.", __FUNCTION__, cams->drvName);	usb_deregister(&cams->usbdrv);	dbg("%s: Deallocating cams=$%p (%d. cameras)", __FUNCTION__, cams, cams->num_cameras);	for (i=0; i < cams->num_cameras; i++) {		struct uvd *up = &cams->cam[i];		int warning = 0;		if (up->user_data != NULL) {			if (up->user_size <= 0)				++warning;		} else {			if (up->user_size > 0)				++warning;		}		if (warning) {			err("%s: Warning: user_data=$%p user_size=%d.",			    __FUNCTION__, up->user_data, up->user_size);		} else {			dbg("%s: Freeing %d. $%p->user_data=$%p",			    __FUNCTION__, i, up, up->user_data);			kfree(up->user_data);		}	}	/* Whole array was allocated in one chunk */	dbg("%s: Freed %d uvd structures",	    __FUNCTION__, cams->num_cameras);	kfree(cams);	*pCams = NULL;}EXPORT_SYMBOL(usbvideo_Deregister);/* * usbvideo_Disconnect() * * This procedure stops all driver activity. Deallocation of * the interface-private structure (pointed by 'ptr') is done now * (if we don't have any open files) or later, when those files * are closed. After that driver should be removable. * * This code handles surprise removal. The uvd->user is a counter which * increments on open() and decrements on close(). If we see here that * this counter is not 0 then we have a client who still has us opened. * We set uvd->remove_pending flag as early as possible, and after that * all access to the camera will gracefully fail. These failures should * prompt client to (eventually) close the video device, and then - in * usbvideo_v4l_close() - we decrement uvd->uvd_used and usage counter. * * History: * 22-Jan-2000 Added polling of MOD_IN_USE to delay removal until all users gone. * 27-Jan-2000 Reworked to allow pending disconnects; see xxx_close() * 24-May-2000 Corrected to prevent race condition (MOD_xxx_USE_COUNT). * 19-Oct-2000 Moved to usbvideo module. */static void usbvideo_Disconnect(struct usb_interface *intf){	struct uvd *uvd = usb_get_intfdata (intf);	int i;	if (uvd == NULL) {		err("%s($%p): Illegal call.", __FUNCTION__, intf);		return;	}	usb_set_intfdata (intf, NULL);	usbvideo_ClientIncModCount(uvd);	if (uvd->debug > 0)		info("%s(%p.)", __FUNCTION__, intf);	down(&uvd->lock);	uvd->remove_pending = 1; /* Now all ISO data will be ignored */	/* At this time we ask to cancel outstanding URBs */	GET_CALLBACK(uvd, stopDataPump)(uvd);	for (i=0; i < USBVIDEO_NUMSBUF; i++)		usb_free_urb(uvd->sbuf[i].urb);	usb_put_dev(uvd->dev);	uvd->dev = NULL;    	    /* USB device is no more */	video_unregister_device(&uvd->vdev);	if (uvd->debug > 0)		info("%s: Video unregistered.", __FUNCTION__);	if (uvd->user)		info("%s: In use, disconnect pending.", __FUNCTION__);	else		usbvideo_CameraRelease(uvd);	up(&uvd->lock);	info("USB camera disconnected.");	usbvideo_ClientDecModCount(uvd);}/* * usbvideo_CameraRelease() * * This code does final release of uvd. This happens * after the device is disconnected -and- all clients * closed their files. * * History: * 27-Jan-2000 Created. */static void usbvideo_CameraRelease(struct uvd *uvd){	if (uvd == NULL) {		err("%s: Illegal call", __FUNCTION__);		return;	}	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(struct usbvideo *cams){	int u, rv = -1;	if (cams == NULL) {		err("No usbvideo handle?");		return -1;	}	down(&cams->lock);	for (u = 0; u < cams->num_cameras; u++) {		struct uvd *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;}static struct file_operations usbvideo_fops = {	.owner =  THIS_MODULE,	.open =   usbvideo_v4l_open,	.release =usbvideo_v4l_close,	.read =   usbvideo_v4l_read,	.mmap =   usbvideo_v4l_mmap,	.ioctl =  usbvideo_v4l_ioctl,	.llseek = no_llseek,};static struct video_device usbvideo_template = {	.owner =      THIS_MODULE,	.type =       VID_TYPE_CAPTURE,	.hardware =   VID_HARDWARE_CPIA,	.fops =       &usbvideo_fops,};struct uvd *usbvideo_AllocateDevice(struct usbvideo *cams){	int i, devnum;	struct uvd *uvd = NULL;	if (cams == NULL) {		err("No usbvideo 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, GFP_KERNEL);		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 */	uvd->vdev = usbvideo_template;	sprintf(uvd->vdev.name, "%.20s USB Camera", cams->drvName);	/*	 * 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;}EXPORT_SYMBOL(usbvideo_AllocateDevice);int usbvideo_RegisterVideoDevice(struct uvd *uvd){	char tmp1[20], tmp2[20];	/* Buffers for printing */	if (uvd == NULL) {		err("%s: Illegal call.", __FUNCTION__);		return -EINVAL;	}	if (uvd->video_endp == 0) {		info("%s: No video endpoint specified; data pump disabled.", __FUNCTION__);	}	if (uvd->paletteBits == 0) {		err("%s: No palettes specified!", __FUNCTION__);		return -EINVAL;	}	if (uvd->defaultPalette == 0) {		info("%s: No default palette!", __FUNCTION__);	}	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",		     __FUNCTION__, 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", __FUNCTION__);		return -EPIPE;	}	if (uvd->debug > 1) {		info("%s: video_register_device() successful", __FUNCTION__);	}	if (uvd->dev == NULL) {		err("%s: uvd->dev == NULL", __FUNCTION__);		return -EINVAL;	}	info("%s on /dev/video%d: canvas=%s videosize=%s",	     (uvd->handle != NULL) ? uvd->handle->drvName : "???",	     uvd->vdev.minor, tmp2, tmp1);	usb_get_dev(uvd->dev);	return 0;}EXPORT_SYMBOL(usbvideo_RegisterVideoDevice);/* ******************************************************************** */static int usbvideo_v4l_mmap(struct file *file, struct vm_area_struct *vma){	struct uvd *uvd = file->private_data;	unsigned long start = vma->vm_start;	unsigned long size  = vma->vm_end-vma->vm_start;	unsigned long page, pos;	if (!CAMERA_IS_OPERATIONAL(uvd))		return -EFAULT;	if (size > (((USBVIDEO_NUMFRAMES * uvd->max_frame_size) + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1)))		return -EINVAL;	pos = (unsigned long) uvd->fbuf;	while (size > 0) {		page = vmalloc_to_pfn((void *)pos);		if (remap_pfn_range(vma, 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;}

⌨️ 快捷键说明

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