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

📄 ibmcam.c

📁 Linux内核源代码 为压缩文件 是<<Linux内核>>一书中的源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
/* * USB IBM C-It Video Camera driver * * Supports IBM C-It Video Camera. * * This driver is based on earlier work of: * * (C) Copyright 1999 Johannes Erdfelt * (C) Copyright 1999 Randy Dunlap * * 5/24/00 Removed optional (and unnecessary) locking of the driver while * the device remains plugged in. Corrected race conditions in ibmcam_open * and ibmcam_probe() routines using this as a guideline: * * (2) The big kernel lock is automatically released when a process sleeps *   in the kernel and is automatically reacquired on reschedule if the *   process had the lock originally.  Any code that can be compiled as *   a module and is entered with the big kernel lock held *MUST* *   increment the use count to activate the indirect module protection *   before doing anything that might sleep. * *   In practice, this means that all routines that live in modules and *   are invoked under the big kernel lock should do MOD_INC_USE_COUNT *   as their very first action.  And all failure paths from that *   routine must do MOD_DEC_USE_COUNT before returning. */#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/init.h>#include <linux/spinlock.h>#include <linux/usb.h>#include <asm/io.h>#include "ibmcam.h"#define	ENABLE_HEXDUMP	0	/* Enable if you need it */static int debug = 0;/* Completion states of the data parser */typedef enum {	scan_Continue,		/* Just parse next item */	scan_NextFrame,		/* Frame done, send it to V4L */	scan_Out,		/* Not enough data for frame */	scan_EndParse		/* End parsing */} scan_state_t;/* Bit flags (options) */#define FLAGS_RETRY_VIDIOCSYNC		(1 << 0)#define	FLAGS_MONOCHROME		(1 << 1)#define FLAGS_DISPLAY_HINTS		(1 << 2)#define FLAGS_OVERLAY_STATS		(1 << 3)#define FLAGS_FORCE_TESTPATTERN		(1 << 4)#define FLAGS_SEPARATE_FRAMES		(1 << 5)#define FLAGS_CLEAN_FRAMES		(1 << 6)static int flags = 0; /* FLAGS_DISPLAY_HINTS | FLAGS_OVERLAY_STATS; *//* This is the size of V4L frame that we provide */static const int imgwidth = V4L_FRAME_WIDTH_USED;static const int imgheight = V4L_FRAME_HEIGHT;static const int min_imgwidth  = 8;static const int min_imgheight = 4;static int lighting = 1; /* Medium */#define SHARPNESS_MIN	0#define SHARPNESS_MAX	6static int sharpness = 4; /* Low noise, good details */#define FRAMERATE_MIN	0#define FRAMERATE_MAX	6static int framerate = 2; /* Lower, reliable frame rate (8-12 fps) */enum {	VIDEOSIZE_128x96 = 0,	VIDEOSIZE_176x144,	VIDEOSIZE_352x288,	VIDEOSIZE_320x240,	VIDEOSIZE_352x240,};static int videosize = VIDEOSIZE_352x288;/* * The value of 'scratchbufsize' affects quality of the picture * in many ways. Shorter buffers may cause loss of data when client * is too slow. Larger buffers are memory-consuming and take longer * to work with. This setting can be adjusted, but the default value * should be OK for most desktop users. */#define DEFAULT_SCRATCH_BUF_SIZE	(0x10000)	/* 64 KB */static const int scratchbufsize = DEFAULT_SCRATCH_BUF_SIZE;/* * Here we define several initialization variables. They may * be used to automatically set color, hue, brightness and * contrast to desired values. This is particularly useful in * case of webcams (which have no controls and no on-screen * output) and also when a client V4L software is used that * does not have some of those controls. In any case it's * good to have startup values as options. * * These values are all in [0..255] range. This simplifies * operation. Note that actual values of V4L variables may * be scaled up (as much as << 8). User can see that only * on overlay output, however, or through a V4L client. */static int init_brightness = 128;static int init_contrast = 192;static int init_color = 128;static int init_hue = 128;static int hue_correction = 128;/* Settings for camera model 2 */static int init_model2_rg = -1;static int init_model2_rg2 = -1;static int init_model2_sat = -1;static int init_model2_yb = -1;MODULE_PARM(debug, "i");MODULE_PARM_DESC(debug, "Debug level: 0-9 (default=0)");MODULE_PARM(flags, "i");MODULE_PARM_DESC(flags, "Bitfield: 0=VIDIOCSYNC, 1=B/W, 2=show hints, 3=show stats, 4=test pattern, 5=seperate frames, 6=clean frames");MODULE_PARM(framerate, "i");MODULE_PARM_DESC(framerate, "Framerate setting: 0=slowest, 6=fastest (default=2)");MODULE_PARM(lighting, "i");MODULE_PARM_DESC(lighting, "Photosensitivity: 0=bright, 1=medium (default), 2=low light");MODULE_PARM(sharpness, "i");MODULE_PARM_DESC(sharpness, "Model1 noise reduction: 0=smooth, 6=sharp (default=4)");MODULE_PARM(videosize, "i");MODULE_PARM_DESC(videosize, "Image size: 0=128x96, 1=176x144, 2=352x288, 3=320x240, 4=352x240 (default=1)");MODULE_PARM(init_brightness, "i");MODULE_PARM_DESC(init_brightness, "Brightness preconfiguration: 0-255 (default=128)");MODULE_PARM(init_contrast, "i");MODULE_PARM_DESC(init_contrast, "Contrast preconfiguration: 0-255 (default=192)");MODULE_PARM(init_color, "i");MODULE_PARM_DESC(init_color, "Dolor preconfiguration: 0-255 (default=128)");MODULE_PARM(init_hue, "i");MODULE_PARM_DESC(init_hue, "Hue preconfiguration: 0-255 (default=128)");MODULE_PARM(hue_correction, "i");MODULE_PARM_DESC(hue_correction, "YUV colorspace regulation: 0-255 (default=128)");MODULE_PARM(init_model2_rg, "i");MODULE_PARM_DESC(init_model2_rg, "Model2 preconfiguration: 0-255 (default=112)");MODULE_PARM(init_model2_rg2, "i");MODULE_PARM_DESC(init_model2_rg2, "Model2 preconfiguration: 0-255 (default=47)");MODULE_PARM(init_model2_sat, "i");MODULE_PARM_DESC(init_model2_sat, "Model2 preconfiguration: 0-255 (default=52)");MODULE_PARM(init_model2_yb, "i");MODULE_PARM_DESC(init_model2_yb, "Model2 preconfiguration: 0-255 (default=160)");MODULE_AUTHOR ("module author");MODULE_DESCRIPTION ("IBM/Xirlink C-it USB Camera Driver for Linux (c) 2000");/* Still mysterious i2c commands */static const unsigned short unknown_88 = 0x0088;static const unsigned short unknown_89 = 0x0089;static const unsigned short bright_3x[3] = { 0x0031, 0x0032, 0x0033 };static const unsigned short contrast_14 = 0x0014;static const unsigned short light_27 = 0x0027;static const unsigned short sharp_13 = 0x0013;/* i2c commands for Model 2 cameras */static const unsigned short mod2_brightness = 0x001a;		/* $5b .. $ee; default=$5a */static const unsigned short mod2_set_framerate = 0x001c;	/* 0 (fast).. $1F (slow) */static const unsigned short mod2_color_balance_rg2 = 0x001e;	/* 0 (red) .. $7F (green) */static const unsigned short mod2_saturation = 0x0020;		/* 0 (b/w) - $7F (full color) */static const unsigned short mod2_color_balance_yb = 0x0022;	/* 0..$7F, $50 is about right */static const unsigned short mod2_color_balance_rg = 0x0024;	/* 0..$7F, $70 is about right */static const unsigned short mod2_sensitivity = 0x0028;		/* 0 (min) .. $1F (max) */#define MAX_IBMCAM	4struct usb_ibmcam cams[MAX_IBMCAM];/*******************************//* Memory management functions *//*******************************/#define MDEBUG(x)	do { } while(0)		/* Debug memory management */static struct usb_driver ibmcam_driver;static void usb_ibmcam_release(struct usb_ibmcam *ibmcam);/* 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 = (unsigned long) page_address(pte_page(pte));				ret |= (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_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 = 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;}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(virt_to_page(__va(page)));		adr += PAGE_SIZE;		if (size > PAGE_SIZE)			size -= PAGE_SIZE;		else			size = 0;	}	vfree(mem);}#if ENABLE_HEXDUMPstatic void ibmcam_hexdump(const unsigned char *data, int len){	char tmp[80];	int i, k;	for (i=k=0; len > 0; i++, len--) {		if (i > 0 && (i%16 == 0)) {			printk("%s\n", tmp);			k=0;		}		k += sprintf(&tmp[k], "%02x ", data[i]);	}	if (k > 0)		printk("%s\n", tmp);}#endif/* * usb_ibmcam_overlaychar() * * History: * 1/2/00   Created. */void usb_ibmcam_overlaychar(	struct usb_ibmcam *ibmcam,	struct ibmcam_frame *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 ((ibmcam == 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) {				IBMCAM_PUTPIXEL(frame, x+ix, y+iy, 0xFF, 0xFF, 0xFF);			}			digit = digit << 1;		}	}}/* * usb_ibmcam_overlaystring() * * History: * 1/2/00   Created. */void usb_ibmcam_overlaystring(	struct usb_ibmcam *ibmcam,	struct ibmcam_frame *frame,	int x, int y, const char *str){	while (*str) {		usb_ibmcam_overlaychar(ibmcam, frame, x, y, *str);		str++;		x += 4; /* 3 pixels character + 1 space */	}}/* * usb_ibmcam_overlaystats() * * Overlays important debugging information. * * History: * 1/2/00   Created. */void usb_ibmcam_overlaystats(struct usb_ibmcam *ibmcam, struct ibmcam_frame *frame){	const int y_diff = 8;	char tmp[16];	int x = 10;	int y = 10;	sprintf(tmp, "%8x", ibmcam->frame_num);	usb_ibmcam_overlaystring(ibmcam, frame, x, y, tmp);	y += y_diff;	sprintf(tmp, "%8lx", ibmcam->urb_count);	usb_ibmcam_overlaystring(ibmcam, frame, x, y, tmp);	y += y_diff;	sprintf(tmp, "%8lx", ibmcam->urb_length);	usb_ibmcam_overlaystring(ibmcam, frame, x, y, tmp);	y += y_diff;	sprintf(tmp, "%8lx", ibmcam->data_count);	usb_ibmcam_overlaystring(ibmcam, frame, x, y, tmp);	y += y_diff;	sprintf(tmp, "%8lx", ibmcam->header_count);	usb_ibmcam_overlaystring(ibmcam, frame, x, y, tmp);	y += y_diff;

⌨️ 快捷键说明

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