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

📄 quickcam_messenger.c

📁 trident tm5600的linux驱动
💻 C
📖 第 1 页 / 共 2 页
字号:
		if ((fhdr->id) == cpu_to_be16(0x8001)) {			RingQueue_Enqueue(&uvd->dp, marker, 4);			totaldata += 4;			continue;		}		if ((fhdr->id & cpu_to_be16(0xFF00)) == cpu_to_be16(0x0200)) {			RingQueue_Enqueue(&uvd->dp, cdata, datalen);			totaldata += datalen;		}		framelen -= datalen;		cdata += datalen;	}	return totaldata;}static int qcm_compress_iso(struct uvd *uvd, struct urb *dataurb){	int totlen;	int i;	unsigned char *cdata;	totlen=0;	for (i = 0; i < dataurb->number_of_packets; i++) {		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;		if (st < 0) {			dev_warn(&uvd->dev->dev,				 "Data error: packet=%d. len=%d. status=%d.\n",				 i, n, st);			uvd->stats.iso_err_count++;			continue;		}		if (!n)			continue;		totlen += qcm_process_frame(uvd, cdata, n);	}	return totlen;}static void resubmit_urb(struct uvd *uvd, struct urb *urb){	int ret;	urb->dev = uvd->dev;	ret = usb_submit_urb(urb, GFP_ATOMIC);	if (ret)		err("usb_submit_urb error (%d)", ret);}#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19)static void qcm_isoc_irq(struct urb *urb, struct pt_regs *regs)#elsestatic void qcm_isoc_irq(struct urb *urb)#endif{	int len;	struct uvd *uvd = urb->context;	if (!CAMERA_IS_OPERATIONAL(uvd))		return;	if (!uvd->streaming)		return;	uvd->stats.urb_count++;	if (!urb->actual_length) {		resubmit_urb(uvd, urb);		return;	}	len = qcm_compress_iso(uvd, urb);	resubmit_urb(uvd, urb);	uvd->stats.urb_length = len;	uvd->stats.data_count += len;	if (len)		RingQueue_WakeUpInterruptible(&uvd->dp);}static int qcm_start_data(struct uvd *uvd){	struct qcm *cam = (struct qcm *) uvd->user_data;	int i;	int errflag;	int pktsz;	int err;	pktsz = uvd->iso_packet_len;	if (!CAMERA_IS_OPERATIONAL(uvd)) {		err("Camera is not operational");		return -EFAULT;	}	err = usb_set_interface(uvd->dev, uvd->iface, uvd->ifaceAltActive);	if (err < 0) {		err("usb_set_interface error");		uvd->last_error = err;		return -EBUSY;	}	for (i=0; i < USBVIDEO_NUMSBUF; i++) {		int j, k;		struct urb *urb = uvd->sbuf[i].urb;		urb->dev = uvd->dev;		urb->context = uvd;		urb->pipe = usb_rcvisocpipe(uvd->dev, uvd->video_endp);		urb->interval = 1;		urb->transfer_flags = URB_ISO_ASAP;		urb->transfer_buffer = uvd->sbuf[i].data;		urb->complete = qcm_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;		}	}	uvd->streaming = 1;	uvd->curframe = -1;	for (i=0; i < USBVIDEO_NUMSBUF; i++) {		errflag = usb_submit_urb(uvd->sbuf[i].urb, GFP_KERNEL);		if (errflag)			err ("usb_submit_isoc(%d) ret %d", i, errflag);	}	CHECK_RET(err, qcm_setup_input_int(cam, uvd));	CHECK_RET(err, qcm_camera_on(uvd));	return 0;}static void qcm_stop_data(struct uvd *uvd){	struct qcm *cam = (struct qcm *) uvd->user_data;	int i, j;	int ret;	if ((uvd == NULL) || (!uvd->streaming) || (uvd->dev == NULL))		return;	ret = qcm_camera_off(uvd);	if (ret)		dev_warn(&uvd->dev->dev, "couldn't turn the cam off.\n");	uvd->streaming = 0;	/* Unschedule all of the iso td's */	for (i=0; i < USBVIDEO_NUMSBUF; i++)		usb_kill_urb(uvd->sbuf[i].urb);	qcm_stop_int_data(cam);	if (!uvd->remove_pending) {		/* Set packet size to 0 */		j = usb_set_interface(uvd->dev, uvd->iface,					uvd->ifaceAltInactive);		if (j < 0) {			err("usb_set_interface() error %d.", j);			uvd->last_error = j;		}	}}static void qcm_process_isoc(struct uvd *uvd, struct usbvideo_frame *frame){	struct qcm *cam = (struct qcm *) uvd->user_data;	int x;	struct rgb *rgbL0;	struct rgb *rgbL1;	struct bayL0 *bayL0;	struct bayL1 *bayL1;	int hor,ver,hordel,verdel;	assert(frame != NULL);	switch (cam->size) {	case SIZE_160X120:		hor = 162; ver = 124; hordel = 1; verdel = 2;		break;	case SIZE_320X240:	default:		hor = 324; ver = 248; hordel = 2; verdel = 4;		break;	}	if (frame->scanstate == ScanState_Scanning) {		while (RingQueue_GetLength(&uvd->dp) >=			 4 + (hor*verdel + hordel)) {			if ((RING_QUEUE_PEEK(&uvd->dp, 0) == 0x00) &&			    (RING_QUEUE_PEEK(&uvd->dp, 1) == 0xff) &&			    (RING_QUEUE_PEEK(&uvd->dp, 2) == 0x00) &&			    (RING_QUEUE_PEEK(&uvd->dp, 3) == 0xff)) {				frame->curline = 0;				frame->scanstate = ScanState_Lines;				frame->frameState = FrameState_Grabbing;				RING_QUEUE_DEQUEUE_BYTES(&uvd->dp, 4);			/*			* if we're starting, we need to discard the first			* 4 lines of y bayer data			* and the first 2 gr elements of x bayer data			*/				RING_QUEUE_DEQUEUE_BYTES(&uvd->dp,							(hor*verdel + hordel));				break;			}			RING_QUEUE_DEQUEUE_BYTES(&uvd->dp, 1);		}	}	if (frame->scanstate == ScanState_Scanning)		return;	/* now we can start processing bayer data so long as we have at least	* 2 lines worth of data. this is the simplest demosaicing method that	* I could think of. I use each 2x2 bayer element without interpolation	* to generate 4 rgb pixels.	*/	while ( frame->curline < cam->height &&		(RingQueue_GetLength(&uvd->dp) >= hor*2)) {		/* get 2 lines of bayer for demosaicing		 * into 2 lines of RGB */		RingQueue_Dequeue(&uvd->dp, cam->scratch, hor*2);		bayL0 = (struct bayL0 *) cam->scratch;		bayL1 = (struct bayL1 *) (cam->scratch + hor);		/* frame->curline is the rgb y line */		rgbL0 = (struct rgb *)				( frame->data + (cam->width*3*frame->curline));		/* w/2 because we're already doing 2 pixels */		rgbL1 = rgbL0 + (cam->width/2);		for (x=0; x < cam->width; x+=2) {			rgbL0->r = bayL0->r;			rgbL0->g = bayL0->g;			rgbL0->b = bayL1->b;			rgbL0->r2 = bayL0->r;			rgbL0->g2 = bayL1->g;			rgbL0->b2 = bayL1->b;			rgbL1->r = bayL0->r;			rgbL1->g = bayL1->g;			rgbL1->b = bayL1->b;			rgbL1->r2 = bayL0->r;			rgbL1->g2 = bayL1->g;			rgbL1->b2 = bayL1->b;			rgbL0++;			rgbL1++;			bayL0++;			bayL1++;		}		frame->seqRead_Length += cam->width*3*2;		frame->curline += 2;	}	/* See if we filled the frame */	if (frame->curline == cam->height) {		frame->frameState = FrameState_Done_Hold;		frame->curline = 0;		uvd->curframe = -1;		uvd->stats.frame_num++;	}}/* taken from konicawc */static int qcm_set_video_mode(struct uvd *uvd, struct video_window *vw){	int ret;	int newsize;	int oldsize;	int x = vw->width;	int y = vw->height;	struct qcm *cam = (struct qcm *) uvd->user_data;	if (x > 0 && y > 0) {		DEBUG(2, "trying to find size %d,%d", x, y);		for (newsize = 0; newsize <= MAX_FRAME_SIZE; newsize++) {			if ((camera_sizes[newsize].width == x) &&				(camera_sizes[newsize].height == y))				break;		}	} else		newsize = cam->size;	if (newsize > MAX_FRAME_SIZE) {		DEBUG(1, "couldn't find size %d,%d", x, y);		return -EINVAL;	}	if (newsize == cam->size) {		DEBUG(1, "Nothing to do");		return 0;	}	qcm_stop_data(uvd);	if (cam->size != newsize) {		oldsize = cam->size;		cam->size = newsize;		ret = qcm_set_camera_size(uvd);		if (ret) {			err("Couldn't set camera size, err=%d",ret);			/* restore the original size */			cam->size = oldsize;			return ret;		}	}	/* Flush the input queue and clear any current frame in progress */	RingQueue_Flush(&uvd->dp);	if (uvd->curframe != -1) {		uvd->frame[uvd->curframe].curline = 0;		uvd->frame[uvd->curframe].seqRead_Length = 0;		uvd->frame[uvd->curframe].seqRead_Index = 0;	}	CHECK_RET(ret, qcm_start_data(uvd));	return 0;}static int qcm_configure_video(struct uvd *uvd){	int ret;	memset(&uvd->vpic, 0, sizeof(uvd->vpic));	memset(&uvd->vpic_old, 0x55, sizeof(uvd->vpic_old));	uvd->vpic.colour = colour;	uvd->vpic.hue = hue;	uvd->vpic.brightness = brightness;	uvd->vpic.contrast = contrast;	uvd->vpic.whiteness = whiteness;	uvd->vpic.depth = 24;	uvd->vpic.palette = VIDEO_PALETTE_RGB24;	memset(&uvd->vcap, 0, sizeof(uvd->vcap));	strcpy(uvd->vcap.name, "QCM USB Camera");	uvd->vcap.type = VID_TYPE_CAPTURE;	uvd->vcap.channels = 1;	uvd->vcap.audios = 0;	uvd->vcap.minwidth = camera_sizes[SIZE_160X120].width;	uvd->vcap.minheight = camera_sizes[SIZE_160X120].height;	uvd->vcap.maxwidth = camera_sizes[SIZE_320X240].width;	uvd->vcap.maxheight = camera_sizes[SIZE_320X240].height;	memset(&uvd->vchan, 0, sizeof(uvd->vchan));	uvd->vchan.flags = 0 ;	uvd->vchan.tuners = 0;	uvd->vchan.channel = 0;	uvd->vchan.type = VIDEO_TYPE_CAMERA;	strcpy(uvd->vchan.name, "Camera");	CHECK_RET(ret, qcm_sensor_init(uvd));	return 0;}static int qcm_probe(struct usb_interface *intf,			const struct usb_device_id *devid){	int err;	struct uvd *uvd;	struct usb_device *dev = interface_to_usbdev(intf);	struct qcm *cam;	size_t buffer_size;	unsigned char video_ep;	struct usb_host_interface *interface;	struct usb_endpoint_descriptor *endpoint;	int i,j;	unsigned int ifacenum, ifacenum_inact=0;	__le16 sensor_id;	/* we don't support multiconfig cams */	if (dev->descriptor.bNumConfigurations != 1)		return -ENODEV;	/* first check for the video interface and not	* the audio interface */	interface = &intf->cur_altsetting[0];	if ((interface->desc.bInterfaceClass != USB_CLASS_VENDOR_SPEC)		|| (interface->desc.bInterfaceSubClass !=			USB_CLASS_VENDOR_SPEC))		return -ENODEV;	/*	walk through each endpoint in each setting in the interface	stop when we find the one that's an isochronous IN endpoint.	*/	for (i=0; i < intf->num_altsetting; i++) {		interface = &intf->cur_altsetting[i];		ifacenum = interface->desc.bAlternateSetting;		/* walk the end points */		for (j=0; j < interface->desc.bNumEndpoints; j++) {			endpoint = &interface->endpoint[j].desc;			if ((endpoint->bEndpointAddress &				USB_ENDPOINT_DIR_MASK) != USB_DIR_IN)				continue; /* not input then not good */			buffer_size = le16_to_cpu(endpoint->wMaxPacketSize);			if (!buffer_size) {				ifacenum_inact = ifacenum;				continue; /* 0 pkt size is not what we want */			}			if ((endpoint->bmAttributes &				USB_ENDPOINT_XFERTYPE_MASK) ==				USB_ENDPOINT_XFER_ISOC) {				video_ep = endpoint->bEndpointAddress;				/* break out of the search */				goto good_videoep;			}		}	}	/* failed out since nothing useful was found */	err("No suitable endpoint was found\n");	return -ENODEV;good_videoep:	/* disable isochronous stream before doing anything else */	err = qcm_stv_setb(dev, STV_ISO_ENABLE, 0);	if (err < 0) {		err("Failed to disable sensor stream");		return -EIO;	}	/*	Check that this is the same unknown sensor that is known to work. This	sensor is suspected to be the ST VV6422C001. I'll check the same value	that the qc-usb driver checks. This value is probably not even the	sensor ID since it matches the USB dev ID. Oh well. If it doesn't	match, it's probably a diff sensor so exit and apologize.	*/	err = qcm_stv_getw(dev, CMOS_SENSOR_IDREV, &sensor_id);	if (err < 0) {		err("Couldn't read sensor values. Err %d\n",err);		return err;	}	if (sensor_id != cpu_to_le16(0x08F0)) {		err("Sensor ID %x != %x. Unsupported. Sorry\n",			le16_to_cpu(sensor_id), (0x08F0));		return -ENODEV;	}	uvd = usbvideo_AllocateDevice(cams);	if (!uvd)		return -ENOMEM;	cam = (struct qcm *) uvd->user_data;	/* buf for doing demosaicing */	cam->scratch = kmalloc(324*2, GFP_KERNEL);	if (!cam->scratch) /* uvd freed in dereg */		return -ENOMEM;	/* yes, if we fail after here, cam->scratch gets freed	by qcm_free_uvd */	err = qcm_alloc_int_urb(cam);	if (err < 0)		return err;	/* yes, if we fail after here, int urb gets freed	by qcm_free_uvd */	RESTRICT_TO_RANGE(size, SIZE_160X120, SIZE_320X240);	cam->width = camera_sizes[size].width;	cam->height = camera_sizes[size].height;	cam->size = size;	uvd->debug = debug;	uvd->flags = 0;	uvd->dev = dev;	uvd->iface = intf->altsetting->desc.bInterfaceNumber;	uvd->ifaceAltActive = ifacenum;	uvd->ifaceAltInactive = ifacenum_inact;	uvd->video_endp = video_ep;	uvd->iso_packet_len = buffer_size;	uvd->paletteBits = 1L << VIDEO_PALETTE_RGB24;	uvd->defaultPalette = VIDEO_PALETTE_RGB24;	uvd->canvas = VIDEOSIZE(320, 240);	uvd->videosize = VIDEOSIZE(cam->width, cam->height);	err = qcm_configure_video(uvd);	if (err) {		err("failed to configure video settings");		return err;	}	err = usbvideo_RegisterVideoDevice(uvd);	if (err) { /* the uvd gets freed in Deregister */		err("usbvideo_RegisterVideoDevice() failed.");		return err;	}	uvd->max_frame_size = (320 * 240 * 3);	qcm_register_input(cam, dev);	usb_set_intfdata(intf, uvd);	return 0;}static void qcm_free_uvd(struct uvd *uvd){	struct qcm *cam = (struct qcm *) uvd->user_data;	kfree(cam->scratch);	qcm_unregister_input(cam);	qcm_free_int(cam);}static struct usbvideo_cb qcm_driver = {	.probe = 		qcm_probe,	.setupOnOpen = 		qcm_setup_on_open,	.processData = 		qcm_process_isoc,	.setVideoMode = 	qcm_set_video_mode,	.startDataPump = 	qcm_start_data,	.stopDataPump = 	qcm_stop_data,	.adjustPicture = 	qcm_adjust_picture,	.userFree = 		qcm_free_uvd};static int __init qcm_init(void){	printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":"	       DRIVER_DESC "\n");	return usbvideo_register(		&cams,		MAX_CAMERAS,		sizeof(struct qcm),		"QCM",		&qcm_driver,		THIS_MODULE,		qcm_table);}static void __exit qcm_exit(void){	usbvideo_Deregister(&cams);}module_param(size, int, 0);MODULE_PARM_DESC(size, "Initial Size 0: 160x120 1: 320x240");module_param(colour, int, 0);MODULE_PARM_DESC(colour, "Initial colour");module_param(hue, int, 0);MODULE_PARM_DESC(hue, "Initial hue");module_param(brightness, int, 0);MODULE_PARM_DESC(brightness, "Initial brightness");module_param(contrast, int, 0);MODULE_PARM_DESC(contrast, "Initial contrast");module_param(whiteness, int, 0);MODULE_PARM_DESC(whiteness, "Initial whiteness");#ifdef CONFIG_USB_DEBUGmodule_param(debug, int, S_IRUGO | S_IWUSR);MODULE_PARM_DESC(debug, "Debug level: 0-9 (default=0)");#endifmodule_init(qcm_init);module_exit(qcm_exit);MODULE_LICENSE("GPL");MODULE_AUTHOR("Jaya Kumar");MODULE_DESCRIPTION("QCM USB Camera");MODULE_SUPPORTED_DEVICE("QCM USB Camera");

⌨️ 快捷键说明

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