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

📄 qc-driver.c

📁 Webcam Linux driver for Quickcam
💻 C
📖 第 1 页 / 共 5 页
字号:
  107, 108, 110, 111, 113, 114, 115, 117, 118, 120, 121, 123,  124, 126, 127, 128, 130, 131, 133, 134, 136, 137, 139, 140,  142, 143, 145, 146, 148, 149, 151, 152, 154, 156, 157, 159,  160, 162, 163, 165, 166, 168, 170, 171, 173, 174, 176, 178,  179, 181, 182, 184, 186, 187, 189, 190, 192, 194, 195, 197,  199, 200, 202, 204, 205, 207, 209, 210, 212, 214, 215, 217,  219, 221, 222, 224, 226, 227, 229, 231, 233, 234, 236, 238,  240, 241, 243, 245, 247, 248, 250, 252, 254, 255, 255, 255,  255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,  255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,  255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,  255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,  255, 255, 255, 255};#endifstatic void qc_usb_exit(struct quickcam *qc);static int qc_capt_init(struct quickcam *qc);static void qc_capt_exit(struct quickcam *qc);static int qc_capt_get(struct quickcam *qc, unsigned char **frame);static int qc_isoc_init(struct quickcam *qc);static void qc_isoc_exit(struct quickcam *qc);/* }}} *//* {{{ [fold] **** Miscellaneous functions ************************************** */#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,8)/* {{{ [fold] usb_kill_urb(struct urb *urb) *//* Unlink URB synchronously (usb_unlink_urb may not be synchronous). * Note: at this moment the URB completion handler must not resubmit the same URB. */static void qc_usb_kill_urb(struct urb *urb) {  int r;  while ((r=usb_unlink_urb(urb)) == -EBUSY) {    /* The URB is not anymore linked (status!=-EINPROGRESS) but      * usb_unlink_urb() was asynchronous and URB's completion handler still will run */    set_current_state(TASK_UNINTERRUPTIBLE);    schedule_timeout( (HZ/100)==0 ? 1 : HZ/100);  }  /* if (r!=-EBUSY),   * usb_unlink_urb() called synchronously the completion handler and   * there's no need to wait or anything else */  if (r) PDEBUG("qc_usb_kill_urb(%p): r=%i", urb, r);}#undef usb_kill_urb#define usb_kill_urb(urb)      qc_usb_kill_urb(urb)/* }}} */#endif/* {{{ [fold] qc_usleep(long usec) */void qc_usleep(unsigned long usec){	wait_queue_head_t wq;	init_waitqueue_head(&wq);	interruptible_sleep_on_timeout(&wq, usec*(HZ/1000000));}void qc_msleep(unsigned long usec){	wait_queue_head_t wq;	init_waitqueue_head(&wq);	interruptible_sleep_on_timeout(&wq, usec*(HZ/1000));}/* }}} *//* {{{ [fold] int qc_stv_set(struct quickcam *qc, unsigned short reg, unsigned char val) *//* * Set one byte register in the STV-chip. */int qc_stv_set(struct quickcam *qc, unsigned short reg, unsigned char val){	int ret;	if (qcdebug&QC_DEBUGLOGIC || qcdebug&QC_DEBUGCAMERA) PDEBUG("qc_stv_set(qc=%p,reg=0x%04X,val=%u)",qc,(int)reg,(int)val);	TEST_BUGR(qc==NULL);	ret = usb_control_msg(qc->dev, usb_sndctrlpipe(qc->dev, 0),			      0x04,			/* Request */			      0x40,			/* RequestType */			      reg, 0,			/* Value, Index */			      &val, 1, 3*HZ);	if ((qcdebug&QC_DEBUGERRORS || qcdebug&QC_DEBUGLOGIC) && ret<0) PDEBUG("Failed qc_stv_set()=%i", ret);	if (ret<0) return ret;	return 0;}/* }}} *//* {{{ [fold] int qc_stv_get(struct quickcam *qc, unsigned short reg, unsigned char *val) *//* * Read one byte register in the STV-chip. * Return the unsigned register value or negative error code on error. */int qc_stv_get(struct quickcam *qc, unsigned short reg, unsigned char *val){	int ret;	if (qcdebug&QC_DEBUGLOGIC || qcdebug&QC_DEBUGCAMERA) PDEBUG("qc_stv_get(qc=%p,reg=0x%04X)",qc,(int)reg);	TEST_BUGR(qc==NULL);	ret = usb_control_msg(qc->dev, usb_rcvctrlpipe(qc->dev, 0),			      0x04,			/* Request */			      0xC0,			/* RequestType */			      reg, 0,			/* Value, Index */			      val, 1, 3*HZ);	if ((qcdebug&QC_DEBUGERRORS || qcdebug&QC_DEBUGLOGIC) && ret<0) PDEBUG("Failed qc_stv_get()=%i", ret);	if (ret<0) return ret;	if (qcdebug&QC_DEBUGCAMERA) PDEBUG("qc_stv_get(reg=0x%04X)=%02X", reg, *val);	return 0;}int qc_stv_getw(struct quickcam *qc, unsigned short reg, __le16 *val){	int ret;	if (qcdebug&QC_DEBUGLOGIC || qcdebug&QC_DEBUGCAMERA) PDEBUG("qc_stv_get(qc=%p,reg=0x%04X)",qc,(int)reg);	TEST_BUGR(qc==NULL);	ret = usb_control_msg(qc->dev, usb_rcvctrlpipe(qc->dev, 0),			      0x04,			/* Request */			      0xC0,			/* RequestType */			      reg, 0,			/* Value, Index */			      val, 2, 3*HZ);	if ((qcdebug&QC_DEBUGERRORS || qcdebug&QC_DEBUGLOGIC) && ret<0) PDEBUG("Failed qc_stv_get()=%i", ret);	if (ret<0) return ret;	if (qcdebug&QC_DEBUGCAMERA) PDEBUG("qc_stv_getw(reg=0x%04X)=%02X", reg, le16_to_cpu(*val));	return 0;}/* }}} *//* {{{ [fold] int qc_stv_setw(struct quickcam *qc, unsigned short reg, unsigned short val) *//* * Set two byte register in the STV-chip. * "w" means either "word" or "wide", depending on your religion ;) */int qc_stv_setw(struct quickcam *qc, unsigned short reg, unsigned short val){	int ret;	if (qcdebug&QC_DEBUGLOGIC || qcdebug&QC_DEBUGCAMERA) PDEBUG("qc_stv_setw(qc=%p,reg=0x%04X,val=%i)",qc,(int)reg,(int)val);	TEST_BUGR(qc==NULL);	ret = usb_control_msg(qc->dev, usb_sndctrlpipe(qc->dev, 0),		0x04,		0x40,		reg, 0,		&val,		2, 3*HZ);	if ((qcdebug&QC_DEBUGERRORS || qcdebug&QC_DEBUGLOGIC) && ret<0) PDEBUG("Failed qc_stv_setw()=%i", ret);	if (ret<0) return ret;	return 0;}/* }}} *//* {{{ [fold] void qc_hsv2rgb(s16 hue, u16 sat, u16 val, int *red, int *green, int *blue) *//* Convert HSI (hue, saturation, intensity) to RGB (red, green, blue). * All input and output values are 0..65535. * Hue is actually signed, so it is -32768..32767, but this is equivalent * since it is the angle around full circle (0=Red, 21845=Green, 43690=Blue). * Based on libgimp, converted to 16.16 fixed point by tuukkat. */void qc_hsv2rgb(s16 hue, u16 sat, u16 val, int *red, int *green, int *blue){	unsigned int segment, valsat;	signed int   h = (u16)hue;	unsigned int s = (sat<32768) ? 0 : (sat-32768)*2;	/* 32768 or less = no saturation */	unsigned int v = val;					/* value = intensity */	unsigned int p;#if 1	/* Make common case more efficient */	if (s == 0) {		*red   = v;		*green = v;		*blue  = v;		return;	}#endif	segment = (h + 10923) & 0xFFFF;			segment = segment*3 >> 16;		/* 0..2: 0=R, 1=G, 2=B */	hue -= segment * 21845;			/* -10923..10923 */	h = hue;	h *= 3;	valsat = v*s >> 16;			/* 0..65534 */	p = v - valsat;	if (h>=0) {		unsigned int t = v - (valsat * (32769 - h) >> 15);		switch (segment) {		default:			PDEBUG("hsi2rgb: this can never happen!");		case 0:	/* R-> */			*red   = v;			*green = t;			*blue  = p;			break;		case 1:	/* G-> */			*red   = p;			*green = v;			*blue  = t;			break;		case 2:	/* B-> */			*red   = t;			*green = p;			*blue  = v;			break;		}	} else {		unsigned int q = v - (valsat * (32769 + h) >> 15);		switch (segment) {		default:			PDEBUG("hsi2rgb: this can never happen!");		case 0:	/* ->R */			*red   = v;			*green = p;			*blue  = q;			break;		case 1:	/* ->G */			*red   = q;			*green = v;			*blue  = p;			break;		case 2:	/* ->B */			*red   = p;			*green = q;			*blue  = v;			break;		}	}	//PDEBUG("hue=%i sat=%i val=%i  segment=%i h=%i  r=%i g=%i b=%i",hue,sat,val, segment,h, *red,*green,*blue);}/* }}} *//* {{{ [fold] int qc_lock(struct quickcam *qc) *//* Takes a lock on quickcam_list_lock and verifies that the given qc is available *//* Returns 0 on success in which case the lock must be freed later or negative error code */static int qc_lock(struct quickcam *qc){	struct quickcam *q;	if (down_interruptible(&quickcam_list_lock)) return -ERESTARTSYS;	/* Search for the device in the list of plugged quickcams (this prevents a race condition) */	list_for_each_entry(q, &quickcam_list, list) {		if (q == qc) break;			/* Found it? */	}	if (q != qc) {		PDEBUG("can not find the device to open");		up(&quickcam_list_lock);		return -ENODEV;	}	return 0;}/* }}} */int qc_i2c_wait(struct quickcam *qc){	// just a dummy function for all old calls	return 0;}int qc_int_abort(struct quickcam *qc){	struct qc_int_data *id = &qc->int_data;	int r = 0;	if (qcdebug&QC_DEBUGLOGIC) PDEBUG("qc_int_abort(quickcam=%p)",qc);	TEST_BUGR(in_interrupt());	TEST_BUGR(qc==NULL);	IDEBUG_TEST(*id);	/* This is to abort INT URBs with timeout. I don't see any other	 * good way to be sure it won't be re-submitted again. */	id->abort_polling = 1;        if(NOT_POISONED_PTR(id->urb)) {	  /*	  r = qc_unlink_urb_sync(id->urb);	  if(r<0) PDEBUG("qc_int_abort: error unlink_urb %d", r);	  */	  usb_kill_urb(id->urb);#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)	  /* make sure interrupt is executed one last time. Just in case	   * polling already was set to 0 by misstake */	  wait_ms(100);#endif	  r = wait_event_interruptible(id->wq, id->polling==0);	  if(r<0) PDEBUG("qc_int_abort: wait_event_interruptible returned %d", r);	}	return 0;}#ifndef DISABLE_INT_URBS#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) && LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20)static void qc_int_handler(struct urb *urb, struct pt_regs *ptregs)#elsestatic void qc_int_handler(struct urb *urb)#endif{	struct quickcam *qc = urb->context;	struct qc_int_data *id;	int r = 0;	if (qcdebug&QC_DEBUGINTERRUPTS) PDEBUG("[INTR] qc_int_handler(urb=%p)",urb);	TEST_BUG(urb==NULL);	TEST_BUG(qc==NULL);	IDEBUG_TEST(qc->int_data);	id = &qc->int_data;	if (qcdebug&QC_DEBUGLOGIC)	{	  PDEBUG("INT URB status=%i tb_length=%i act_length=%i interval=%d frame=%d data=%02X", 		 urb->status, urb->transfer_buffer_length, urb->actual_length,		 urb->interval,		 urb->start_frame,		 ((unsigned char *)urb->transfer_buffer)[0]);	}	if(qc->dev == NULL) {	  /* if we have a postponed exit, this will exit this function */	  PDEBUG("qc_int_handler: qc->dev == NULL");	  goto end2;	}	if (urb->status<0) {		urb->actual_length = 0;  // reset length		urb->transfer_buffer_length = 1;		switch (urb->status) {		case -ECONNABORTED:		  // 2.4 kernels return this after timeout		  break;		case -ESHUTDOWN:	/* Shutdown */		  if ((jiffies-int_init_jiffy) < HZ/4) {		    PDEBUG("Very quick shutdown in int_handler !!");		    PDEBUG("The driver probably failed to initialize the usb-interface.");		    PDEBUG("Please reload module:  rmmod quickcam ; modprobe quickcam");		  }		case -ECONNRESET:	/* Asynchronous unlink, should not happen */		case -ENODEV:		/* Device was removed */		case -ENOENT:		/* URB was unlinked */		  goto endpolling;		default:		  PDEBUG("Unhandled INT URB error %i",urb->status);		case -EPROTO:		/* Bitstuff error or unknown USB error */		case -EILSEQ:		/* CRC mismatch (seen when unplugging camera and at postponed exit) */		case -ETIMEDOUT:	/* Transfer timed out */		case -EREMOTEIO:	/* Short packet detected */		case -EPIPE:		/* Babble detect or endpoint stalled */			/* We could try resubmitting the URB here */			id->errorcount++;#if 1			PDEBUG("INT URB error status=%i tb_length=%i act_length=%i interval=%d frame=%d data=%02X", 			       urb->status, urb->transfer_buffer_length, urb->actual_length,			       urb->interval,			       urb->start_frame,			       ((unsigned char *)urb->transfer_buffer)[0]);#endif#if 0			goto endpolling;#else			urb->actual_length = 0;			urb->transfer_buffer_length = 1;						if(id->abort_polling) {			  PDEBUG("end due to abort_polling");			  goto endpolling;			}			if (qcdebug&QC_DEBUGLOGIC) PDEBUG("submit_urb called()");#if 0			if(urb->dev != qc->dev) {			  PDEBUG("urb->dev != qc->dev %p %p", urb->dev, qc->dev);			  urb->dev = qc->dev;			}#endif

⌨️ 快捷键说明

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