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

📄 usbvideo.c

📁 基于S3CEB2410平台LINUX操作系统下 USB驱动源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
/* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */#include <linux/kernel.h>#include <linux/sched.h>#include <linux/list.h>#include <linux/slab.h>#define	__NO_VERSION__		/* Temporary: usbvideo is not a module yet */#include <linux/module.h>#include <linux/mm.h>#include <linux/smp_lock.h>#include <linux/vmalloc.h>#include <linux/wrapper.h>#include <linux/init.h>#include <linux/spinlock.h>#include <asm/io.h>#include "usbvideo.h"#if defined(MAP_NR)#define	virt_to_page(v)	MAP_NR(v)	/* Kernels 2.2.x */#endifstatic int video_nr = -1;MODULE_PARM(video_nr, "i");/* * Local prototypes. */#if USES_PROC_FSstatic void usbvideo_procfs_level1_create(usbvideo_t *ut);static void usbvideo_procfs_level1_destroy(usbvideo_t *ut);static void usbvideo_procfs_level2_create(uvd_t *uvd);static void usbvideo_procfs_level2_destroy(uvd_t *uvd);static int usbvideo_default_procfs_read_proc(	char *page, char **start, off_t off, int count,	int *eof, void *data);static int usbvideo_default_procfs_write_proc(	struct file *file, const char *buffer, 	unsigned long count, void *data);#endif/*******************************//* Memory management functions *//*******************************/#define MDEBUG(x)	do { } while(0)		/* Debug memory management *//* Given PGD from the address space's page table, return the kernel * virtual mapping of the physical memory mapped at ADR. */unsigned long usbvideo_uvirt_to_kva(pgd_t *pgd, unsigned long adr){	unsigned long ret = 0UL;	pmd_t *pmd;	pte_t *ptep, pte;	if (!pgd_none(*pgd)) {		pmd = pmd_offset(pgd, adr);		if (!pmd_none(*pmd)) {			ptep = pte_offset(pmd, adr);			pte = *ptep;			if (pte_present(pte)) {				ret = (unsigned long) page_address(pte_page(pte));				ret |= (adr & (PAGE_SIZE-1));			}		}	}	MDEBUG(printk("uv2kva(%lx-->%lx)", adr, ret));	return ret;}/* * Here we want the physical address of the memory. * This is used when initializing the contents of the * area and marking the pages as reserved. */unsigned long usbvideo_kvirt_to_pa(unsigned long adr){	unsigned long va, kva, ret;	va = VMALLOC_VMADDR(adr);	kva = usbvideo_uvirt_to_kva(pgd_offset_k(va), va);	ret = __pa(kva);	MDEBUG(printk("kv2pa(%lx-->%lx)", adr, ret));	return ret;}void *usbvideo_rvmalloc(unsigned long size){	void *mem;	unsigned long adr, page;	/* Round it off to PAGE_SIZE */	size += (PAGE_SIZE - 1);	size &= ~(PAGE_SIZE - 1);	mem = vmalloc_32(size);	if (!mem)		return NULL;	memset(mem, 0, size); /* Clear the ram out, no junk to the user */	adr = (unsigned long) mem;	while (size > 0) {		page = usbvideo_kvirt_to_pa(adr);		mem_map_reserve(virt_to_page(__va(page)));		adr += PAGE_SIZE;		if (size > PAGE_SIZE)			size -= PAGE_SIZE;		else			size = 0;	}	return mem;}void usbvideo_rvfree(void *mem, unsigned long size){	unsigned long adr, page;	if (!mem)		return;	size += (PAGE_SIZE - 1);	size &= ~(PAGE_SIZE - 1);	adr=(unsigned long) mem;	while (size > 0) {		page = usbvideo_kvirt_to_pa(adr);		mem_map_unreserve(virt_to_page(__va(page)));		adr += PAGE_SIZE;		if (size > PAGE_SIZE)			size -= PAGE_SIZE;		else			size = 0;	}	vfree(mem);}void RingQueue_Initialize(RingQueue_t *rq){	assert(rq != NULL);	init_waitqueue_head(&rq->wqh);}void RingQueue_Allocate(RingQueue_t *rq, int rqLen){	assert(rq != NULL);	assert(rqLen > 0);	rq->length = rqLen;	rq->queue = usbvideo_rvmalloc(rq->length);	assert(rq->queue != NULL);}int RingQueue_IsAllocated(const RingQueue_t *rq){	if (rq == NULL)		return 0;	return (rq->queue != NULL) && (rq->length > 0);}void RingQueue_Free(RingQueue_t *rq){	assert(rq != NULL);	if (RingQueue_IsAllocated(rq)) {		usbvideo_rvfree(rq->queue, rq->length);		rq->queue = NULL;		rq->length = 0;	}}int RingQueue_Dequeue(RingQueue_t *rq, unsigned char *dst, int len){	int i;	assert(rq != NULL);	assert(dst != NULL);	for (i=0; i < len; i++) {		dst[i] = rq->queue[rq->ri];		RING_QUEUE_DEQUEUE_BYTES(rq,1);	}	return len;}int RingQueue_Enqueue(RingQueue_t *rq, const unsigned char *cdata, int n){	int enqueued = 0;	assert(rq != NULL);	assert(cdata != NULL);	assert(rq->length > 0);	while (n > 0) {		int m, q_avail;		/* Calculate the largest chunk that fits the tail of the ring */		q_avail = rq->length - rq->wi;		if (q_avail <= 0) {			rq->wi = 0;			q_avail = rq->length;		}		m = n;		assert(q_avail > 0);		if (m > q_avail)			m = q_avail;		memmove(rq->queue + rq->wi, cdata, m);		RING_QUEUE_ADVANCE_INDEX(rq, wi, m);		cdata += m;		enqueued += m;		n -= m;	}	return enqueued;}int RingQueue_GetLength(const RingQueue_t *rq){	int ri, wi;	assert(rq != NULL);	ri = rq->ri;	wi = rq->wi;	if (ri == wi)		return 0;	else if (ri < wi)		return wi - ri;	else		return wi + (rq->length - ri);}void RingQueue_InterruptibleSleepOn(RingQueue_t *rq){	assert(rq != NULL);	interruptible_sleep_on(&rq->wqh);}void RingQueue_WakeUpInterruptible(RingQueue_t *rq){	assert(rq != NULL);	if (waitqueue_active(&rq->wqh))		wake_up_interruptible(&rq->wqh);}/* * usbvideo_VideosizeToString() * * This procedure converts given videosize value to readable string. * * History: * 07-Aug-2000 Created. * 19-Oct-2000 Reworked for usbvideo module. */void usbvideo_VideosizeToString(char *buf, int bufLen, videosize_t vs){	char tmp[40];	int n;	n = 1 + sprintf(tmp, "%ldx%ld", VIDEOSIZE_X(vs), VIDEOSIZE_Y(vs));	assert(n < sizeof(tmp));	if ((buf == NULL) || (bufLen < n))		err("usbvideo_VideosizeToString: buffer is too small.");	else		memmove(buf, tmp, n);}/* * usbvideo_OverlayChar() * * History: * 01-Feb-2000 Created. */void usbvideo_OverlayChar(uvd_t *uvd, usbvideo_frame_t *frame,			  int x, int y, int ch){	static const unsigned short digits[16] = {		0xF6DE, /* 0 */		0x2492, /* 1 */		0xE7CE, /* 2 */		0xE79E, /* 3 */		0xB792, /* 4 */		0xF39E, /* 5 */		0xF3DE, /* 6 */		0xF492, /* 7 */		0xF7DE, /* 8 */		0xF79E, /* 9 */		0x77DA, /* a */		0xD75C, /* b */		0xF24E, /* c */		0xD6DC, /* d */		0xF34E, /* e */		0xF348  /* f */	};	unsigned short digit;	int ix, iy;	if ((uvd == NULL) || (frame == NULL))		return;	if (ch >= '0' && ch <= '9')		ch -= '0';	else if (ch >= 'A' && ch <= 'F')		ch = 10 + (ch - 'A');	else if (ch >= 'a' && ch <= 'f')		ch = 10 + (ch - 'a');	else		return;	digit = digits[ch];	for (iy=0; iy < 5; iy++) {		for (ix=0; ix < 3; ix++) {			if (digit & 0x8000) {				if (uvd->paletteBits & (1L << VIDEO_PALETTE_RGB24)) {/* TODO */				RGB24_PUTPIXEL(frame, x+ix, y+iy, 0xFF, 0xFF, 0xFF);				}			}			digit = digit << 1;		}	}}/* * usbvideo_OverlayString() * * History: * 01-Feb-2000 Created. */void usbvideo_OverlayString(uvd_t *uvd, usbvideo_frame_t *frame,			    int x, int y, const char *str){	while (*str) {		usbvideo_OverlayChar(uvd, frame, x, y, *str);		str++;		x += 4; /* 3 pixels character + 1 space */	}}/* * usbvideo_OverlayStats() * * Overlays important debugging information. * * History: * 01-Feb-2000 Created. */void usbvideo_OverlayStats(uvd_t *uvd, usbvideo_frame_t *frame){	const int y_diff = 8;	char tmp[16];	int x = 10, y=10;	long i, j, barLength;	const int qi_x1 = 60, qi_y1 = 10;	const int qi_x2 = VIDEOSIZE_X(frame->request) - 10, qi_h = 10;	/* Call the user callback, see if we may proceed after that */	if (VALID_CALLBACK(uvd, overlayHook)) {		if (GET_CALLBACK(uvd, overlayHook)(uvd, frame) < 0)			return;	}	/*	 * We draw a (mostly) hollow rectangle with qi_xxx coordinates.	 * Left edge symbolizes the queue index 0; right edge symbolizes	 * the full capacity of the queue.	 */	barLength = qi_x2 - qi_x1 - 2;	if ((barLength > 10) && (uvd->paletteBits & (1L << VIDEO_PALETTE_RGB24))) {/* TODO */	long u_lo, u_hi, q_used;		long m_ri, m_wi, m_lo, m_hi;		/*		 * Determine fill zones (used areas of the queue):		 * 0 xxxxxxx u_lo ...... uvd->dp.ri xxxxxxxx u_hi ..... uvd->dp.length		 *		 * if u_lo < 0 then there is no first filler.		 */		q_used = RingQueue_GetLength(&uvd->dp);		if ((uvd->dp.ri + q_used) >= uvd->dp.length) {			u_hi = uvd->dp.length;			u_lo = (q_used + uvd->dp.ri) % uvd->dp.length;		} else {			u_hi = (q_used + uvd->dp.ri);			u_lo = -1;		}		/* Convert byte indices into screen units */		m_ri = qi_x1 + ((barLength * uvd->dp.ri) / uvd->dp.length);		m_wi = qi_x1 + ((barLength * uvd->dp.wi) / uvd->dp.length);		m_lo = (u_lo > 0) ? (qi_x1 + ((barLength * u_lo) / uvd->dp.length)) : -1;		m_hi = qi_x1 + ((barLength * u_hi) / uvd->dp.length);		for (j=qi_y1; j < (qi_y1 + qi_h); j++) {			for (i=qi_x1; i < qi_x2; i++) {				/* Draw border lines */				if ((j == qi_y1) || (j == (qi_y1 + qi_h - 1)) ||				    (i == qi_x1) || (i == (qi_x2 - 1))) {					RGB24_PUTPIXEL(frame, i, j, 0xFF, 0xFF, 0xFF);					continue;				}				/* For all other points the Y coordinate does not matter */				if ((i >= m_ri) && (i <= (m_ri + 3))) {					RGB24_PUTPIXEL(frame, i, j, 0x00, 0xFF, 0x00);				} else if ((i >= m_wi) && (i <= (m_wi + 3))) {					RGB24_PUTPIXEL(frame, i, j, 0xFF, 0x00, 0x00);				} else if ((i < m_lo) || ((i > m_ri) && (i < m_hi)))					RGB24_PUTPIXEL(frame, i, j, 0x00, 0x00, 0xFF);			}		}	}	sprintf(tmp, "%8lx", uvd->stats.frame_num);	usbvideo_OverlayString(uvd, frame, x, y, tmp);	y += y_diff;	sprintf(tmp, "%8lx", uvd->stats.urb_count);	usbvideo_OverlayString(uvd, frame, x, y, tmp);	y += y_diff;	sprintf(tmp, "%8lx", uvd->stats.urb_length);	usbvideo_OverlayString(uvd, frame, x, y, tmp);	y += y_diff;	sprintf(tmp, "%8lx", uvd->stats.data_count);	usbvideo_OverlayString(uvd, frame, x, y, tmp);	y += y_diff;	sprintf(tmp, "%8lx", uvd->stats.header_count);	usbvideo_OverlayString(uvd, frame, x, y, tmp);	y += y_diff;	sprintf(tmp, "%8lx", uvd->stats.iso_skip_count);	usbvideo_OverlayString(uvd, frame, x, y, tmp);	y += y_diff;	sprintf(tmp, "%8lx", uvd->stats.iso_err_count);	usbvideo_OverlayString(uvd, frame, x, y, tmp);	y += y_diff;	sprintf(tmp, "%8x", uvd->vpic.colour);	usbvideo_OverlayString(uvd, frame, x, y, tmp);	y += y_diff;	sprintf(tmp, "%8x", uvd->vpic.hue);	usbvideo_OverlayString(uvd, frame, x, y, tmp);	y += y_diff;	sprintf(tmp, "%8x", uvd->vpic.brightness >> 8);	usbvideo_OverlayString(uvd, frame, x, y, tmp);	y += y_diff;	sprintf(tmp, "%8x", uvd->vpic.contrast >> 12);	usbvideo_OverlayString(uvd, frame, x, y, tmp);	y += y_diff;	sprintf(tmp, "%8d", uvd->vpic.whiteness >> 8);	usbvideo_OverlayString(uvd, frame, x, y, tmp);	y += y_diff;}/* * usbvideo_ReportStatistics() * * This procedure prints packet and transfer statistics. * * History: * 14-Jan-2000 Corrected default multiplier. */void usbvideo_ReportStatistics(const uvd_t *uvd){	if ((uvd != NULL) && (uvd->stats.urb_count > 0)) {		unsigned long allPackets, badPackets, goodPackets, percent;		allPackets = uvd->stats.urb_count * CAMERA_URB_FRAMES;		badPackets = uvd->stats.iso_skip_count + uvd->stats.iso_err_count;		goodPackets = allPackets - badPackets;

⌨️ 快捷键说明

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