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

📄 konicawc.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * konicawc.c - konica webcam driver * * Author: Simon Evans <spse@secret.org.uk> * * Copyright (C) 2002 Simon Evans * * Licence: GPL * * Driver for USB webcams based on Konica chipset. This * chipset is used in Intel YC76 camera. * */#include <linux/kernel.h>#include <linux/module.h>#include <linux/init.h>#include <linux/input.h>#include <linux/usb_input.h>#include "usbvideo.h"#define MAX_BRIGHTNESS	108#define MAX_CONTRAST	108#define MAX_SATURATION	108#define MAX_SHARPNESS	108#define MAX_WHITEBAL	372#define MAX_SPEED	6#define MAX_CAMERAS	1#define DRIVER_VERSION	"v1.4"#define DRIVER_DESC	"Konica Webcam driver"enum ctrl_req {	SetWhitebal	= 0x01,	SetBrightness	= 0x02,        SetSharpness	= 0x03,	SetContrast	= 0x04,	SetSaturation	= 0x05,};enum frame_sizes {	SIZE_160X120	= 0,	SIZE_160X136	= 1,	SIZE_176X144	= 2,	SIZE_320X240	= 3,	};#define MAX_FRAME_SIZE	SIZE_320X240static struct usbvideo *cams;#ifdef CONFIG_USB_DEBUGstatic int debug;#define DEBUG(n, format, arg...) \	if (n <= debug) {	 \		printk(KERN_DEBUG __FILE__ ":%s(): " format "\n", __FUNCTION__ , ## arg); \	}#else#define DEBUG(n, arg...)static const int debug = 0;#endif/* Some default values for initial camera settings,   can be set by modprobe */static int size;	static int speed = 6;		/* Speed (fps) 0 (slowest) to 6 (fastest) */static int brightness =	MAX_BRIGHTNESS/2;static int contrast =	MAX_CONTRAST/2;static int saturation =	MAX_SATURATION/2;static int sharpness =	MAX_SHARPNESS/2;static int whitebal =	3*(MAX_WHITEBAL/4);static int spd_to_iface[] = { 1, 0, 3, 2, 4, 5, 6 };/* These FPS speeds are from the windows config box. They are * indexed on size (0-2) and speed (0-6). Divide by 3 to get the * real fps. */static int spd_to_fps[][7] = { { 24, 40, 48, 60, 72, 80, 100 },			       { 24, 40, 48, 60, 72, 80, 100 },			       { 18, 30, 36, 45, 54, 60, 75  },			       { 6,  10, 12, 15, 18, 21, 25  } };struct cam_size {	u16	width;	u16	height;	u8	cmd;};static struct cam_size camera_sizes[] = { { 160, 120, 0x7 },					  { 160, 136, 0xa },					  { 176, 144, 0x4 },					  { 320, 240, 0x5 } };struct konicawc {	u8 brightness;		/* camera uses 0 - 9, x11 for real value */	u8 contrast;		/* as above */	u8 saturation;		/* as above */	u8 sharpness;		/* as above */	u8 white_bal;		/* 0 - 33, x11 for real value */	u8 speed;		/* Stored as 0 - 6, used as index in spd_to_* (above) */	u8 size;		/* Frame Size */	int height;	int width;	struct urb *sts_urb[USBVIDEO_NUMSBUF];	u8 sts_buf[USBVIDEO_NUMSBUF][FRAMES_PER_DESC];	struct urb *last_data_urb;	int lastframe;	int cur_frame_size;	/* number of bytes in current frame size */	int maxline;		/* number of lines per frame */	int yplanesz;		/* Number of bytes in the Y plane */	unsigned int buttonsts:1;#ifdef CONFIG_INPUT	struct input_dev *input;	char input_physname[64];#endif};#define konicawc_set_misc(uvd, req, value, index)		konicawc_ctrl_msg(uvd, USB_DIR_OUT, req, value, index, NULL, 0)#define konicawc_get_misc(uvd, req, value, index, buf, sz)	konicawc_ctrl_msg(uvd, USB_DIR_IN, req, value, index, buf, sz)#define konicawc_set_value(uvd, value, index)			konicawc_ctrl_msg(uvd, USB_DIR_OUT, 2, value, index, NULL, 0)static int konicawc_ctrl_msg(struct uvd *uvd, u8 dir, u8 request, u16 value, u16 index, void *buf, int len){        int retval = usb_control_msg(uvd->dev,		dir ? usb_rcvctrlpipe(uvd->dev, 0) : usb_sndctrlpipe(uvd->dev, 0),		    request, 0x40 | dir, value, index, buf, len, 1000);        return retval < 0 ? retval : 0;}static inline void konicawc_camera_on(struct uvd *uvd){        DEBUG(0, "camera on");        konicawc_set_misc(uvd, 0x2, 1, 0x0b);}static inline void konicawc_camera_off(struct uvd *uvd){        DEBUG(0, "camera off");        konicawc_set_misc(uvd, 0x2, 0, 0x0b);}static void konicawc_set_camera_size(struct uvd *uvd){	struct konicawc *cam = (struct konicawc *)uvd->user_data;	konicawc_set_misc(uvd, 0x2, camera_sizes[cam->size].cmd, 0x08);	cam->width = camera_sizes[cam->size].width;	cam->height = camera_sizes[cam->size].height;	cam->yplanesz = cam->height * cam->width;	cam->cur_frame_size = (cam->yplanesz * 3) / 2;	cam->maxline = cam->yplanesz / 256;	uvd->videosize = VIDEOSIZE(cam->width, cam->height);}static int konicawc_setup_on_open(struct uvd *uvd){	struct konicawc *cam = (struct konicawc *)uvd->user_data;	DEBUG(1, "setting brightness to %d (%d)", cam->brightness,	    cam->brightness * 11);	konicawc_set_value(uvd, cam->brightness, SetBrightness);	DEBUG(1, "setting white balance to %d (%d)", cam->white_bal,	    cam->white_bal * 11);	konicawc_set_value(uvd, cam->white_bal, SetWhitebal);	DEBUG(1, "setting contrast to %d (%d)", cam->contrast,	    cam->contrast * 11);	konicawc_set_value(uvd, cam->contrast, SetContrast);	DEBUG(1, "setting saturation to %d (%d)", cam->saturation,	    cam->saturation * 11);	konicawc_set_value(uvd, cam->saturation, SetSaturation);	DEBUG(1, "setting sharpness to %d (%d)", cam->sharpness,	    cam->sharpness * 11);	konicawc_set_value(uvd, cam->sharpness, SetSharpness);	konicawc_set_camera_size(uvd);	cam->lastframe = -2;	cam->buttonsts = 0;	return 0;}static void konicawc_adjust_picture(struct uvd *uvd){	struct konicawc *cam = (struct konicawc *)uvd->user_data;	konicawc_camera_off(uvd);	DEBUG(1, "new brightness: %d", uvd->vpic.brightness);	uvd->vpic.brightness = (uvd->vpic.brightness > MAX_BRIGHTNESS) ? MAX_BRIGHTNESS : uvd->vpic.brightness;	if(cam->brightness != uvd->vpic.brightness / 11) {	   cam->brightness = uvd->vpic.brightness / 11;	   DEBUG(1, "setting brightness to %d (%d)", cam->brightness,	       cam->brightness * 11);	   konicawc_set_value(uvd, cam->brightness, SetBrightness);	}	DEBUG(1, "new contrast: %d", uvd->vpic.contrast);	uvd->vpic.contrast = (uvd->vpic.contrast > MAX_CONTRAST) ? MAX_CONTRAST : uvd->vpic.contrast;	if(cam->contrast != uvd->vpic.contrast / 11) {		cam->contrast = uvd->vpic.contrast / 11;		DEBUG(1, "setting contrast to %d (%d)", cam->contrast,		    cam->contrast * 11);		konicawc_set_value(uvd, cam->contrast, SetContrast);	}	konicawc_camera_on(uvd);}#ifdef CONFIG_INPUTstatic void konicawc_register_input(struct konicawc *cam, struct usb_device *dev){	struct input_dev *input_dev;	usb_make_path(dev, cam->input_physname, sizeof(cam->input_physname));	strncat(cam->input_physname, "/input0", sizeof(cam->input_physname));	cam->input = input_dev = input_allocate_device();	if (!input_dev) {		warn("Not enough memory for camera's input device\n");		return;	}	input_dev->name = "Konicawc snapshot button";	input_dev->phys = cam->input_physname;	usb_to_input_id(dev, &input_dev->id);	input_dev->cdev.dev = &dev->dev;	input_dev->evbit[0] = BIT(EV_KEY);	input_dev->keybit[LONG(BTN_0)] = BIT(BTN_0);	input_dev->private = cam;	input_register_device(cam->input);}static void konicawc_unregister_input(struct konicawc *cam){	if (cam->input) {		input_unregister_device(cam->input);		cam->input = NULL;	}}static void konicawc_report_buttonstat(struct konicawc *cam){	if (cam->input) {		input_report_key(cam->input, BTN_0, cam->buttonsts);		input_sync(cam->input);	}}#elsestatic inline void konicawc_register_input(struct konicawc *cam, struct usb_device *dev) { }static inline void konicawc_unregister_input(struct konicawc *cam) { }static inline void konicawc_report_buttonstat(struct konicawc *cam) { }#endif /* CONFIG_INPUT */static int konicawc_compress_iso(struct uvd *uvd, struct urb *dataurb, struct urb *stsurb){	char *cdata;	int i, totlen = 0;	unsigned char *status = stsurb->transfer_buffer;	int keep = 0, discard = 0, bad = 0;	struct konicawc *cam = (struct konicawc *)uvd->user_data;	for (i = 0; i < dataurb->number_of_packets; i++) {		int button = cam->buttonsts;		unsigned char sts;		int n = dataurb->iso_frame_desc[i].actual_length;		int st = dataurb->iso_frame_desc[i].status;		cdata = dataurb->transfer_buffer +			dataurb->iso_frame_desc[i].offset;		/* Detect and ignore errored packets */		if (st < 0) {			DEBUG(1, "Data error: packet=%d. len=%d. status=%d.",			      i, n, st);			uvd->stats.iso_err_count++;			continue;		}		/* Detect and ignore empty packets */		if (n <= 0) {			uvd->stats.iso_skip_count++;			continue;		}		/* See what the status data said about the packet */		sts = *(status+stsurb->iso_frame_desc[i].offset);		/* sts: 0x80-0xff: frame start with frame number (ie 0-7f)		 * otherwise:		 * bit 0 0: keep packet		 *	 1: drop packet (padding data)		 *		 * bit 4 0 button not clicked		 *       1 button clicked		 * button is used to `take a picture' (in software)		 */		if(sts < 0x80) {			button = !!(sts & 0x40);			sts &= ~0x40;		}				/* work out the button status, but don't do		   anything with it for now */		if(button != cam->buttonsts) {			DEBUG(2, "button: %sclicked", button ? "" : "un");			cam->buttonsts = button;			konicawc_report_buttonstat(cam);		}		if(sts == 0x01) { /* drop frame */			discard++;			continue;		}				if((sts > 0x01) && (sts < 0x80)) {			info("unknown status %2.2x", sts);			bad++;			continue;		}		if(!sts && cam->lastframe == -2) {			DEBUG(2, "dropping frame looking for image start");			continue;		}		keep++;		if(sts & 0x80) { /* frame start */			unsigned char marker[] = { 0, 0xff, 0, 0x00 };			if(cam->lastframe == -2) {				DEBUG(2, "found initial image");				cam->lastframe = -1;			}							marker[3] = sts & 0x7F;			RingQueue_Enqueue(&uvd->dp, marker, 4);			totlen += 4;		}		totlen += n;	/* Little local accounting */		RingQueue_Enqueue(&uvd->dp, cdata, n);	}	DEBUG(8, "finished: keep = %d discard = %d bad = %d added %d bytes",		    keep, discard, bad, totlen);	return totlen;}static void resubmit_urb(struct uvd *uvd, struct urb *urb){        int i, ret;        for (i = 0; i < FRAMES_PER_DESC; i++) {                urb->iso_frame_desc[i].status = 0;        }        urb->dev = uvd->dev;        urb->status = 0;	ret = usb_submit_urb(urb, GFP_ATOMIC);	DEBUG(3, "submitting urb of length %d", urb->transfer_buffer_length);        if(ret)                err("usb_submit_urb error (%d)", ret);}static void konicawc_isoc_irq(struct urb *urb, struct pt_regs *regs){	struct uvd *uvd = urb->context;	struct konicawc *cam = (struct konicawc *)uvd->user_data;	/* We don't want to do anything if we are about to be removed! */	if (!CAMERA_IS_OPERATIONAL(uvd))		return;	if (!uvd->streaming) {		DEBUG(1, "Not streaming, but interrupt!");		return;	}	DEBUG(3, "got frame %d len = %d buflen =%d", urb->start_frame, urb->actual_length, urb->transfer_buffer_length);	uvd->stats.urb_count++;	if (urb->transfer_buffer_length > 32) {		cam->last_data_urb = urb;		return;	}	/* Copy the data received into ring queue */	if(cam->last_data_urb) {		int len = 0;		if(urb->start_frame != cam->last_data_urb->start_frame)			err("Lost sync on frames");		else if (!urb->status && !cam->last_data_urb->status)			len = konicawc_compress_iso(uvd, cam->last_data_urb, urb);		resubmit_urb(uvd, cam->last_data_urb);		resubmit_urb(uvd, urb);		cam->last_data_urb = NULL;		uvd->stats.urb_length = len;		uvd->stats.data_count += len;		if(len)			RingQueue_WakeUpInterruptible(&uvd->dp);		return;	}	return;}static int konicawc_start_data(struct uvd *uvd){	struct usb_device *dev = uvd->dev;	int i, errFlag;	struct konicawc *cam = (struct konicawc *)uvd->user_data;	int pktsz;	struct usb_interface *intf;	struct usb_host_interface *interface = NULL;	intf = usb_ifnum_to_if(dev, uvd->iface);	if (intf)		interface = usb_altnum_to_altsetting(intf,				spd_to_iface[cam->speed]);	if (!interface)		return -ENXIO;	pktsz = le16_to_cpu(interface->endpoint[1].desc.wMaxPacketSize);	DEBUG(1, "pktsz = %d", pktsz);	if (!CAMERA_IS_OPERATIONAL(uvd)) {		err("Camera is not operational");		return -EFAULT;	}	uvd->curframe = -1;	konicawc_camera_on(uvd);	/* Alternate interface 1 is is the biggest frame size */	i = usb_set_interface(dev, uvd->iface, uvd->ifaceAltActive);	if (i < 0) {		err("usb_set_interface error");		uvd->last_error = i;		return -EBUSY;	}	/* We double buffer the Iso lists */	for (i=0; i < USBVIDEO_NUMSBUF; i++) {		int j, k;		struct urb *urb = uvd->sbuf[i].urb;		urb->dev = dev;		urb->context = uvd;		urb->pipe = usb_rcvisocpipe(dev, uvd->video_endp);		urb->interval = 1;		urb->transfer_flags = URB_ISO_ASAP;		urb->transfer_buffer = uvd->sbuf[i].data;		urb->complete = konicawc_isoc_irq;		urb->number_of_packets = FRAMES_PER_DESC;		urb->transfer_buffer_length = pktsz * FRAMES_PER_DESC;		for (j=k=0; j < FRAMES_PER_DESC; j++, k += pktsz) {			urb->iso_frame_desc[j].offset = k;			urb->iso_frame_desc[j].length = pktsz;		}		urb = cam->sts_urb[i];		urb->dev = dev;		urb->context = uvd;		urb->pipe = usb_rcvisocpipe(dev, uvd->video_endp-1);		urb->interval = 1;		urb->transfer_flags = URB_ISO_ASAP;		urb->transfer_buffer = cam->sts_buf[i];		urb->complete = konicawc_isoc_irq;		urb->number_of_packets = FRAMES_PER_DESC;		urb->transfer_buffer_length = FRAMES_PER_DESC;		for (j=0; j < FRAMES_PER_DESC; j++) {			urb->iso_frame_desc[j].offset = j;			urb->iso_frame_desc[j].length = 1;		}	}

⌨️ 快捷键说明

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