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

📄 cpia.c

📁 Usb1.1驱动c语言源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
/* * USB CPiA Video Camera driver * * Supports CPiA based Video Cameras. Many manufacturers use this chipset. * There's a good chance, if you have a USB video camera, it's a CPiA based * one. * * (C) Copyright 1999 Johannes Erdfelt * (C) Copyright 1999 Randy Dunlap */#include <linux/kernel.h>#include <linux/sched.h>#include <linux/list.h>#include <linux/malloc.h>#include <linux/mm.h>#include <linux/smp_lock.h>#include <linux/videodev.h>#include <linux/vmalloc.h>#include <linux/wrapper.h>#include <linux/module.h>#include <linux/spinlock.h>#include <asm/io.h>#include "usb.h"#include "cpia.h"static int debug = 0;MODULE_PARM(debug, "i");/* Video Size 384 x 288 x 3 bytes for RGB *//* 384 because xawtv tries to grab 384 even though we tell it 352 is our max */#define MAX_FRAME_SIZE (384 * 288 * 3)/*******************************//* Memory management functions *//*******************************/#define MDEBUG(x)	do { } while(0)		/* Debug memory management */static struct usb_driver cpia_driver;/* Given PGD from the address space's page table, return the kernel * virtual mapping of the physical memory mapped at ADR. */static inline unsigned long 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 = page_address(pte_page(pte)) | (adr & (PAGE_SIZE-1));		}	}	MDEBUG(printk("uv2kva(%lx-->%lx)", adr, ret));	return ret;}static inline unsigned long uvirt_to_bus(unsigned long adr){	unsigned long kva, ret;	kva = uvirt_to_kva(pgd_offset(current->mm, adr), adr);	ret = virt_to_bus((void *)kva);	MDEBUG(printk("uv2b(%lx-->%lx)", adr, ret));	return ret;}static inline unsigned long kvirt_to_bus(unsigned long adr){	unsigned long va, kva, ret;	va = VMALLOC_VMADDR(adr);	kva = uvirt_to_kva(pgd_offset_k(va), va);	ret = virt_to_bus((void *)kva);	MDEBUG(printk("kv2b(%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. */static inline unsigned long kvirt_to_pa(unsigned long adr){	unsigned long va, kva, ret;	va = VMALLOC_VMADDR(adr);	kva = uvirt_to_kva(pgd_offset_k(va), va);	ret = __pa(kva);	MDEBUG(printk("kv2pa(%lx-->%lx)", adr, ret));	return ret;}static void *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(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 = kvirt_to_pa(adr);		mem_map_reserve(MAP_NR(__va(page)));		adr += PAGE_SIZE;		if (size > PAGE_SIZE)			size -= PAGE_SIZE;		else			size = 0;	}	return mem;}static void 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 = kvirt_to_pa(adr);		mem_map_unreserve(MAP_NR(__va(page)));		adr += PAGE_SIZE;		if (size > PAGE_SIZE)			size -= PAGE_SIZE;		else			size = 0;	}	vfree(mem);}static int usb_cpia_get_version(struct usb_device *dev, void *buf){	return usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),		USB_REQ_CPIA_GET_VERSION,		USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,		0, 0, buf, 4, HZ);}#ifdef NOTUSEDstatic int usb_cpia_get_pnp_id(struct usb_device *dev, void *buf){	return usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),		USB_REQ_CPIA_GET_PNP_ID,		USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,		0, 0, buf, 6, HZ);}#endif#ifdef NOTUSEDstatic int usb_cpia_get_camera_status(struct usb_device *dev, void *buf){	return usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),		USB_REQ_CPIA_GET_CAMERA_STATUS,		USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,		0, 0, buf, 8, HZ);}#endifstatic int usb_cpia_goto_hi_power(struct usb_device *dev){	return usb_control_msg(dev, usb_sndctrlpipe(dev, 0),		USB_REQ_CPIA_GOTO_HI_POWER, USB_TYPE_VENDOR | USB_RECIP_DEVICE,		0, 0, NULL, 0, HZ);}static int usb_cpia_get_vp_version(struct usb_device *dev, void *buf){	return usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),		USB_REQ_CPIA_GET_VP_VERSION,		USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,		0, 0, buf, 4, HZ);}static int usb_cpia_set_sensor_fps(struct usb_device *dev, int sensorbaserate, int sensorclkdivisor){	return usb_control_msg(dev, usb_sndctrlpipe(dev, 0),		USB_REQ_CPIA_SET_SENSOR_FPS,		USB_TYPE_VENDOR | USB_RECIP_DEVICE,		(sensorbaserate << 8) + sensorclkdivisor, 0, NULL, 0, HZ);}#ifdef NOTUSEDstatic int usb_cpia_grab_frame(struct usb_device *dev, int streamstartline){	return usb_control_msg(dev, usb_sndctrlpipe(dev, 0),		USB_REQ_CPIA_GRAB_FRAME, USB_TYPE_VENDOR | USB_RECIP_DEVICE,		streamstartline << 8, 0, NULL, 0, HZ);}#endifstatic int usb_cpia_upload_frame(struct usb_device *dev, int forceupload){	return usb_control_msg(dev, usb_sndctrlpipe(dev, 0),		USB_REQ_CPIA_UPLOAD_FRAME, USB_TYPE_VENDOR | USB_RECIP_DEVICE,		forceupload, 0, NULL, 0, HZ);}static int usb_cpia_set_grab_mode(struct usb_device *dev, int continuousgrab){	return usb_control_msg(dev, usb_sndctrlpipe(dev, 0),		USB_REQ_CPIA_SET_GRAB_MODE,		USB_TYPE_VENDOR | USB_RECIP_DEVICE, continuousgrab,		0, NULL, 0, HZ);}static int usb_cpia_set_format(struct usb_device *dev, int size, int subsample, int order){	return usb_control_msg(dev, usb_sndctrlpipe(dev, 0),		USB_REQ_CPIA_SET_FORMAT,		USB_TYPE_VENDOR | USB_RECIP_DEVICE,		(subsample << 8) + size, order, NULL, 0, HZ);}static int usb_cpia_set_roi(struct usb_device *dev, int colstart, int colend, int rowstart, int rowend){	return usb_control_msg(dev, usb_sndctrlpipe(dev, 0),		USB_REQ_CPIA_SET_ROI,		USB_TYPE_VENDOR | USB_RECIP_DEVICE,		(colend << 8) + colstart, (rowend << 8) + rowstart,		NULL, 0, HZ);}static int usb_cpia_set_compression(struct usb_device *dev, int compmode, int decimation){	return usb_control_msg(dev, usb_sndctrlpipe(dev, 0),		USB_REQ_CPIA_SET_COMPRESSION,		USB_TYPE_VENDOR | USB_RECIP_DEVICE,		(decimation << 8) + compmode, 0, NULL, 0, HZ);}#ifdef NOTUSEDstatic int usb_cpia_set_compression_target(struct usb_device *dev, int target, int targetfr, int targetq){	return usb_control_msg(dev, usb_sndctrlpipe(dev, 0),		USB_REQ_CPIA_SET_COMPRESSION_TARGET,		USB_TYPE_VENDOR | USB_RECIP_DEVICE,		(targetfr << 8) + target, targetq, NULL, 0, HZ);}#endif#ifdef NOTUSEDstatic int usb_cpia_initstreamcap(struct usb_device *dev, int skipframes, int streamstartline){	return usb_control_msg(dev, usb_sndctrlpipe(dev, 0),		USB_REQ_CPIA_INIT_STREAM_CAP,		USB_TYPE_VENDOR | USB_RECIP_DEVICE,		(streamstartline << 8) + skipframes, 0, NULL, 0, HZ);}static int usb_cpia_finistreamcap(struct usb_device *dev){	return usb_control_msg(dev, usb_sndctrlpipe(dev, 0),		USB_REQ_CPIA_FINI_STREAM_CAP,		USB_TYPE_VENDOR | USB_RECIP_DEVICE, 0, 0, NULL, 0, HZ);}static int usb_cpia_startstreamcap(struct usb_device *dev){	return usb_control_msg(dev, usb_sndctrlpipe(dev, 0),		USB_REQ_CPIA_START_STREAM_CAP,		USB_TYPE_VENDOR | USB_RECIP_DEVICE, 0, 0, NULL, 0, HZ);}static int usb_cpia_endstreamcap(struct usb_device *dev){	return usb_control_msg(dev, usb_sndctrlpipe(dev, 0),		USB_REQ_CPIA_END_STREAM_CAP,		USB_TYPE_VENDOR | USB_RECIP_DEVICE, 0, 0, NULL, 0, HZ);}#endif/* How much data is left in the scratch buf? */#define scratch_left(x)	(cpia->scratchlen - (int)((char *)x - (char *)cpia->scratch))static void cpia_parse_data(struct usb_cpia *cpia){	struct cpia_frame *frame, *pframe;	unsigned char *data = cpia->scratch;	unsigned long left;	long copylen = 0;	/* Grab the current frame and the previous frame */	frame = &cpia->frame[cpia->curframe];	pframe = &cpia->frame[(cpia->curframe - 1 + CPIA_NUMFRAMES) % CPIA_NUMFRAMES];	while (1) {		if (!scratch_left(data))			goto out;		switch (frame->scanstate) {		case STATE_SCANNING:		{			struct cpia_frame_header *header;			/* We need at least 2 bytes for the magic value */			if (scratch_left(data) < 2)				goto out;			header = (struct cpia_frame_header *)data;			if (be16_to_cpup(&header->magic) == CPIA_MAGIC) {				frame->scanstate = STATE_HEADER;				break;			}			/* Woops, lost the header, find the end of the frame */			if (scratch_left(data) < 4)				goto out;			/* See if we found the end of the frame */			while (scratch_left(data) >= 4) {				if (*((__u32 *)data) == 0xFFFFFFFF) {					data += 4;					if (debug >= 1)						printk(KERN_INFO "cpia: EOF while scanning for magic\n");					goto error;				}				data++;			}			break;		}		case STATE_HEADER:			/* We need at least 64 bytes for the header */			if (scratch_left(data) <			    sizeof(struct cpia_frame_header))				goto out;			memcpy(&frame->header, data,				sizeof(struct cpia_frame_header));			/* Skip over the header */			data += sizeof(struct cpia_frame_header);			frame->hdrwidth = (frame->header.col_end -				frame->header.col_start) * 8;			frame->hdrheight = (frame->header.row_end -				frame->header.row_start) * 4;			if (debug >= 2) {				printk(KERN_DEBUG "cpia: frame size %dx%d\n",					frame->hdrwidth, frame->hdrheight);				printk(KERN_DEBUG "cpia: frame %scompressed\n",					frame->header.comp_enable ? "" : "not ");			}			frame->scanstate = STATE_LINES;			frame->curline = 0;			break;		case STATE_LINES:		{			unsigned char *f, *end;			unsigned int len;			int i;			int y, u, y1, v, r, g, b;			/* We want at least 2 bytes for the length */			if (scratch_left(data) < 2)				goto out;			/* Grab the length */			len = data[0] + (data[1] << 8);			/* Check to make sure it's nothing outrageous */			if (len > (frame->hdrwidth * 2) + 1) {				if (debug >= 1)					printk(KERN_DEBUG "cpia: bad length, resynching (expected %d, got %d)\n", (frame->hdrwidth * 2) + 1, len);				goto error;			}			/* Make sure there's enough data for the entire line */			if (scratch_left(data + 2) < len)				goto out;			/* Skip over the length */			data += 2;			/* Is the end of the line there */			if (data[len - 1] != 0xFD) {				if (debug >= 1)					printk(KERN_DEBUG "cpia: lost synch\n");				goto error;			}			/* Start at the beginning */			end = data + len - 1;			f = frame->data + (frame->width * 3 * frame->curline);			if (frame->header.comp_enable) {				unsigned char *fp;				/* We use the previous frame as a reference */				fp = pframe->data +					(frame->width * 3 * frame->curline);				while (data < end) {					if (*data & 1) {						/* Compress RLE data */						i = *data >> 1;						memcpy(f, fp, i * 3);						copylen += (i * 3);						f += (i * 3);						fp += (i * 3);						data++;					} else {						/* Raw data */#define LIMIT(x) ((((x)>0xffffff)?0xff0000:(((x)<=0xffff)?0:(x)&0xff0000))>>16)y =  *data++ - 16;u =  *data++ - 128;y1 = *data++ - 16;v =  *data++ - 128;r = 104635 * v;g = -25690 * u + -53294 * v;b = 132278 * u;y  *= 76310;y1 *= 76310;*f++ = LIMIT(b + y); *f++ = LIMIT(g + y); *f++ = LIMIT(r + y);*f++ = LIMIT(b + y1); *f++ = LIMIT(g + y1); *f++ = LIMIT(r + y1);						fp += 6;						copylen += 6;					}				}			} else {				/* Raw data */				while (data < end) {y =  *data++ - 16;u =  *data++ - 128;y1 = *data++ - 16;v =  *data++ - 128;r = 104635 * v;g = -25690 * u + -53294 * v;b = 132278 * u;y  *= 76310;y1 *= 76310;*f++ = LIMIT(b + y); *f++ = LIMIT(g + y); *f++ = LIMIT(r + y);

⌨️ 快捷键说明

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