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

📄 usbvideo.c

📁 基于S3CEB2410平台LINUX操作系统下 USB驱动源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
		/* Calculate percentage wisely, remember integer limits */		assert(allPackets != 0);		if (goodPackets < (((unsigned long)-1)/100))			percent = (100 * goodPackets) / allPackets;		else			percent = goodPackets / (allPackets / 100);		info("Packet Statistics: Total=%lu. Empty=%lu. Usage=%lu%%",		     allPackets, badPackets, percent);		if (uvd->iso_packet_len > 0) {			unsigned long allBytes, xferBytes;			char multiplier = ' ';			allBytes = allPackets * uvd->iso_packet_len;			xferBytes = uvd->stats.data_count;			assert(allBytes != 0);			if (xferBytes < (((unsigned long)-1)/100))				percent = (100 * xferBytes) / allBytes;			else				percent = xferBytes / (allBytes / 100);			/* Scale xferBytes for easy reading */			if (xferBytes > 10*1024) {				xferBytes /= 1024;				multiplier = 'K';				if (xferBytes > 10*1024) {					xferBytes /= 1024;					multiplier = 'M';					if (xferBytes > 10*1024) {						xferBytes /= 1024;						multiplier = 'G';						if (xferBytes > 10*1024) {							xferBytes /= 1024;							multiplier = 'T';						}					}				}			}			info("Transfer Statistics: Transferred=%lu%cB Usage=%lu%%",			     xferBytes, multiplier, percent);		}	}}/* * usbvideo_DrawLine() * * A standard implementation of Bresenham's line drawing algorithm. * This procedure is provided primarily for debugging or demo * purposes. */void usbvideo_DrawLine(	usbvideo_frame_t *frame,	int x1, int y1,	int x2, int y2,	unsigned char cr, unsigned char cg, unsigned char cb){	int i, dx, dy, np, d;	int dinc1, dinc2, x, xinc1, xinc2, y, yinc1, yinc2;	if ((dx = x2 - x1) < 0)		dx = -dx;	if ((dy = y2 - y1) < 0)		dy = -dy;	if (dx >= dy) {		np = dx + 1;		d = (2 * dy) - dx;		dinc1 = dy << 1;		dinc2 = (dy - dx) << 1;		xinc1 = 1;		xinc2 = 1;		yinc1 = 0;		yinc2 = 1;	} else {		np = dy + 1;		d = (2 * dx) - dy;		dinc1 = dx << 1;		dinc2 = (dx - dy) << 1;		xinc1 = 0;		xinc2 = 1;		yinc1 = 1;		yinc2 = 1;	}	/* Make sure x and y move in the right directions */	if (x1 > x2) {		xinc1 = -xinc1;		xinc2 = -xinc2;	}	if (y1 > y2) {		yinc1 = -yinc1;		yinc2 = -yinc2;	}	for (i=0, x=x1, y=y1; i < np; i++) {		if (frame->palette == VIDEO_PALETTE_RGB24) {/* TODO */		RGB24_PUTPIXEL(frame, x, y, cr, cg, cb);		}		if (d < 0) {			d += dinc1;			x += xinc1;			y += yinc1;		} else {			d += dinc2;			x += xinc2;			y += yinc2;		}	}}/* * usbvideo_TestPattern() * * Procedure forms a test pattern (yellow grid on blue background). * * Parameters: * fullframe: if TRUE then entire frame is filled, otherwise the procedure *	      continues from the current scanline. * pmode      0: fill the frame with solid blue color (like on VCR or TV) *	      1: Draw a colored grid * * History: * 01-Feb-2000 Created. */void usbvideo_TestPattern(uvd_t *uvd, int fullframe, int pmode){	static const char proc[] = "usbvideo_TestPattern";	usbvideo_frame_t *frame;	int num_cell = 0;	int scan_length = 0;	static int num_pass = 0;	if (uvd == NULL) {		err("%s: uvd == NULL", proc);		return;	}	if ((uvd->curframe < 0) || (uvd->curframe >= USBVIDEO_NUMFRAMES)) {		err("%s: uvd->curframe=%d.", proc, uvd->curframe);		return;	}	/* Grab the current frame */	frame = &uvd->frame[uvd->curframe];	/* Optionally start at the beginning */	if (fullframe) {		frame->curline = 0;		frame->seqRead_Length = 0;	}#if 0	{	/* For debugging purposes only */		char tmp[20];		usbvideo_VideosizeToString(tmp, sizeof(tmp), frame->request);		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);}/* * 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);}/* Debugging aid */void usbvideo_SayAndWait(const char *what){	wait_queue_head_t wq;	init_waitqueue_head(&wq);	info("Say: %s", what);	interruptible_sleep_on_timeout (&wq, HZ*3); /* Timeout */}/* ******************************************************************** */static void usbvideo_ClientIncModCount(uvd_t *uvd){	static const char proc[] = "usbvideo_ClientIncModCount";	if (uvd == NULL) {		err("%s: uvd == NULL", proc);		return;	}	if (uvd->handle == NULL) {		err("%s: uvd->handle == NULL", proc);		return;	}	if (uvd->handle->md_module == NULL) {		err("%s: uvd->handle->md_module == NULL", proc);		return;	}	__MOD_INC_USE_COUNT(uvd->handle->md_module);}static void usbvideo_ClientDecModCount(uvd_t *uvd){	static const char proc[] = "usbvideo_ClientDecModCount";	if (uvd == NULL) {		err("%s: uvd == NULL", proc);		return;	}	if (uvd->handle == NULL) {		err("%s: uvd->handle == NULL", proc);		return;	}	if (uvd->handle->md_module == NULL) {		err("%s: uvd->handle->md_module == NULL", proc);		return;	}	__MOD_DEC_USE_COUNT(uvd->handle->md_module);}int usbvideo_register(	usbvideo_t **pCams,	const int num_cams,	const int num_extra,	const char *driverName,	const usbvideo_cb_t *cbTbl,	struct module *md ){	static const char proc[] = "usbvideo_register";	usbvideo_t *cams;	int i, base_size;	/* Check parameters for sanity */	if ((num_cams <= 0) || (pCams == NULL) || (cbTbl == NULL)) {		err("%s: Illegal call", proc);		return -EINVAL;	}	/* Check registration callback - must be set! */	if (cbTbl->probe == NULL) {		err("%s: probe() is required!", proc);		return -EINVAL;	}	base_size = num_cams * sizeof(uvd_t) + sizeof(usbvideo_t);	cams = (usbvideo_t *) kmalloc(base_size, GFP_KERNEL);	if (cams == NULL) {		err("Failed to allocate %d. bytes for usbvideo_t", base_size);		return -ENOMEM;	}	dbg("%s: Allocated $%p (%d. bytes) for %d. cameras",	    proc, 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 USES_PROC_FS	/*	 * If both /proc fs callbacks are NULL then we assume that the driver	 * does not need procfs services at all. Leave them NULL.	 */	cams->uses_procfs = (cams->cb.procfs_read != NULL) || (cams->cb.procfs_write == NULL);	if (cams->uses_procfs) {		if (cams->cb.procfs_read == NULL)			cams->cb.procfs_read = usbvideo_default_procfs_read_proc;		if (cams->cb.procfs_write == NULL)			cams->cb.procfs_write = usbvideo_default_procfs_write_proc;	}#else /* !USES_PROC_FS */	/* Report a warning so that user knows why there is no /proc entries */	if ((cams->cb.procfs_read != NULL) || (cams->cb.procfs_write == NULL)) {		dbg("%s: /proc fs support requested but not configured!", proc);	}#endif	cams->num_cameras = num_cams;	cams->cam = (uvd_t *) &cams[1];	cams->md_module = md;	if (cams->md_module == NULL)		warn("%s: module == NULL!", proc);	init_MUTEX(&cams->lock);	/* to 1 == available */	for (i = 0; i < num_cams; i++) {		uvd_t *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) {				up->user_size = 0;				err("%s: Failed to allocate user_data (%d. bytes)",				    proc, up->user_size);				return -ENOMEM;			}			dbg("%s: Allocated cams[%d].user_data=$%p (%d. bytes)",			     proc, 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;#if USES_PROC_FS	if (cams->uses_procfs) {		dbg("%s: Creating /proc filesystem entries.", proc);		usbvideo_procfs_level1_create(cams);	}#endif	/*	 * 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;	usb_register(&cams->usbdrv);	return 0;}/* * 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(usbvideo_t **pCams){	static const char proc[] = "usbvideo_deregister";	usbvideo_t *cams;	int i;	if (pCams == NULL) {		err("%s: pCams == NULL", proc);		return;	}	cams = *pCams;	if (cams == NULL) {		err("%s: cams == NULL", proc);		return;	}#if USES_PROC_FS	if (cams->uses_procfs) {		dbg("%s: Deregistering filesystem entries.", proc);		usbvideo_procfs_level1_destroy(cams);	}#endif	dbg("%s: Deregistering %s driver.", proc, cams->drvName);	usb_deregister(&cams->usbdrv);	dbg("%s: Deallocating cams=$%p (%d. cameras)", proc, cams, cams->num_cameras);	for (i=0; i < cams->num_cameras; i++) {		uvd_t *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.",			    proc, up->user_data, up->user_size);		} else {			dbg("%s: Freeing %d. $%p->user_data=$%p",			    proc, i, up, up->user_data);			kfree(up->user_data);		}	}	/* Whole array was allocated in one chunk */	dbg("%s: Freed %d uvd_t structures",	    proc, cams->num_cameras);	kfree(cams);	*pCams = NULL;}/* * 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. */void usbvideo_Disconnect(struct usb_device *dev, void *ptr){	static const char proc[] = "usbvideo_Disconnect";	uvd_t *uvd = (uvd_t *) ptr;	int i;	if ((dev == NULL) || (uvd == NULL)) {		err("%s($%p,$%p): Illegal call.", proc, dev, ptr);		return;	}	usbvideo_ClientIncModCount(uvd);	if (uvd->debug > 0)		info("%s(%p,%p.)", proc, dev, ptr);	down(&uvd->lock);	uvd->remove_pending = 1; /* Now all ISO data will be ignored */	/* At this time we ask to cancel outstanding URBs */	usbvideo_StopDataPump(uvd);	for (i=0; i < USBVIDEO_NUMSBUF; i++)		usb_free_urb(uvd->sbuf[i].urb);	usb_dec_dev_use(uvd->dev);	uvd->dev = NULL;    	    /* USB device is no more */	if (uvd->user)

⌨️ 快捷键说明

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