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

📄 winbond_9967cf.c

📁 华邦的W996[78]cf芯片组的摄象头驱动程序
💻 C
📖 第 1 页 / 共 2 页
字号:
		       (vw.width==352 && vw.height==288) ||  		       (vw.width==352 && vw.height==288)  ||		       (vw.width==640 && vw.height==480) )			{				printk("w9967cf driver: Resolution not supp"\				       " (%dx%d)",vw.width, vw.height);				return -EINVAL;			}				cam->ctrlreg.width  = vw.width  &~7L;		cam->ctrlreg.height = vw.height &~7L;		//w9967cf_update_registers(cam);				return 0;	}		case VIDIOCGWIN: /* Get Current Window */	{		struct video_window vw;				vw.x = 0;	       		vw.y = 0;		vw.width =  cam->ctrlreg.width;		vw.height = cam->ctrlreg.height; 				vw.chromakey = 0; 		vw.flags = ((cam->ctrlreg.width*cam->ctrlreg.height)>(352*288))			?(15)			:(30);				if (copy_to_user(arg, &vw, sizeof(vw)))			return -EFAULT;				return 0;	}		/* TO DO, don't call */	case VIDIOCGMBUF: /* Request for Memory (mapped) buffer */	{		struct video_mbuf vm;				memset(&vm, 0, sizeof(vm));		vm.size = W9967CF_NUMFRAMES * W9967CF_MAX_DATA_SIZE;		vm.frames = 1;//W9967CF_NUMFRAMES;          		vm.offsets[0] = 0;		vm.offsets[1] = W9967CF_MAX_FRAME_SIZE;		if (copy_to_user(arg, &vm, sizeof(vm)))			return -EFAULT;				return 0;	}		/* To do */	case VIDIOCMCAPTURE:	{		struct video_mmap vm;			if (copy_from_user((void *)&vm, (void *)arg, sizeof(vm)))			return -EFAULT;				if ((vm.format!=VIDEO_PALETTE_YUV420)  && 		    (vm.format!=VIDEO_PALETTE_YUV422)  &&		    (vm.format!=VIDEO_PALETTE_YUV420P) &&		    (vm.format!=VIDEO_PALETTE_YUV422P) )			return -EINVAL;			if (vm.frame >=2)                       return -EINVAL;		if ((vm.width>640) || (vm.height>480))    return -EINVAL;		/* Locks, start a new capture ... */		/* Code to capturinng, locks, others, ... */		/* = vm.width;      	// = vm.height; 	// = vm.format; */				return 0;	}		/* Yet to do!!! */	/* Wait for a frame to be done */	case VIDIOCSYNC:	{		int frame;				if (copy_from_user((void *)&frame, arg, sizeof(int)))			return -EFAULT;				/* Here goes some locks *//*		switch (cam->frame[frame].grabstate) {		case FRAME_GRABBING:	 	case FRAME_DONE: 		{			cam->frame[frame].grabstate = FRAME_UNUSED;		 	break;		}	 	}*/ 		return 0;	}		/* Ignored */	case VIDIOCSFBUF: 		return -EINVAL;	case VIDIOCGFBUF: 	{		struct video_buffer vb;		memset(&vb, 0, sizeof(vb)); //amongst which vb.base		if (copy_to_user(arg, &vb, sizeof(vb)))			return -EFAULT;		return 0;	}	case VIDIOCKEY:		return 0;    	case VIDIOCCAPTURE:                      	case VIDIOCGTUNER:   case VIDIOCSTUNER:  	case VIDIOCGFREQ:    case VIDIOCSFREQ:  	case VIDIOCGAUDIO:   case VIDIOCSAUDIO:		return -EINVAL; 	default:    		return -ENOIOCTLCMD;	} /* end of switch */		return 0; }/* Complete the isoc tranfer    Fill the fbuf with the data received in packets (number_of_packets) by the   USB subsytem.   Currently dumps out only the size and the status for every packet received.   Here goes all the function of data reordering (YUV422 -> RGB, GRAYSCALE)*/static void w9967cf_irq_complete(struct urb *urb){	w9967cfcam *cam;	int i;	if (!urb->context) {		info("No URB context!");		return;	}			cam = (w9967cfcam *)urb->context;	if (!cam->dev) {		info("No usb device!");		return;	}	printk("status = %d\n",urb->status);	for(i=0;i<10;i++) {		int n = urb->iso_frame_desc[i].actual_length;		int st = urb->iso_frame_desc[i].status;		info("n=%d,st=%d",n,st);		memmove(cam->fbuf+i*urb->iso_frame_desc[i].offset,			urb->transfer_buffer + urb->iso_frame_desc[i].offset,			n);		/* Call the function to arrange the data, set the 		 flags for grabbings, locks to buffers (if any)  ...*/	}		return;}/* Init the USB Isoc Transfer    This function initializes the USB subsytem for the isoc tranfer.   It sets the packet size, fills the URB with the correct parameters and submits   it to the USB subsytem.      An isoc transfer causes this function to be called.   This function is w9967cf_irq_complete: fill the fbuf with the data received   extracting it from the packet received. Then return. Actually, this   function only prints the packet size and the error status for every packet   received...   Code in progress... :)*//* Still in progress !!! */static int w9967cf_init_isoc(w9967cfcam *cam) {	urb_t *urb;	int frames,err;	urb = usb_alloc_urb(10);		if (!urb) {		info("Init isoc: error (URB)");		return -ENOMEM;	}			/* w9967cf_stop_capture()? */	/* Set up the structure */	cam->urb                 = urb;	urb->dev                 = cam->dev;	urb->context             = cam;	urb->pipe                = usb_rcvisocpipe(cam->dev, W9967_VIDEO_ENDPOINT);	urb->transfer_flags      = USB_ISO_ASAP;	urb->transfer_buffer     = cam->tbuf;	urb->complete            = w9967cf_irq_complete; 	urb->number_of_packets   = 10; 	urb->transfer_buffer_length = TRANSFER_BUF_SIZE*10;	urb->next = urb;	/* Fill in the offsets and size of every packet */	for(frames=0;frames<10;frames++) {		urb->iso_frame_desc[frames].offset = TRANSFER_BUF_SIZE * frames;		urb->iso_frame_desc[frames].length = TRANSFER_BUF_SIZE;	}		err = usb_submit_urb(urb);	if (err) {		info("Error submitting urb");		return -1;	}	/* w9967cf_init_capture() */	return 0;}/* Allocate the buffers for the driver Note:    - fbuf: The "frame" buffer. This buffer contains the entire frame    - tbuf: Temp buffer for the transfer via usb */ static int w9967cf_allocate_buffers(w9967cfcam *cam) {	if (!(cam->fbuf = rvmalloc(IMG_ALLOC_BUF))) {		info("Cannot allocate fbuf!!!");		return -1;	}	/* Allocate tbuf */	if (!(cam->tbuf = kmalloc(TRANSFER_BUF_SIZE*10, GFP_KERNEL))) {		info("Cannot allocate tbuf!!!");		return -1;	}       	return 0;}/* Deallocate buffers  */static int w9967cf_deallocate_buffers(w9967cfcam *cam) {	if (cam->urb) {		usb_unlink_urb(cam->urb);		usb_free_urb(cam->urb);	}	if (cam->fbuf) 	        rvfree(cam->fbuf,IMG_ALLOC_BUF);	if (cam->tbuf) 		kfree(cam->tbuf);	return 0;}/* * VIDEODEV Register, Deregister, ioctls, ... */static int  w9967cf_init_done(struct video_device *vdev) {	return 0;}/* This function initializes the cam.   The actions are:     - Allocate the buffer for USB and data: w9967cf_allocate_buffers  - Init the isoc transfer for USB: w9967cf_init_isoc  - Basic init of the chip: w9967cf_init_chip  - Increment the user count of the module.*/static int w9967cf_open(struct video_device *vdev, int flags) {	w9967cfcam *cam = (w9967cfcam *)vdev;	info("Allocating buffers...");	if (w9967cf_allocate_buffers(cam)<0) {		return -1;	}	if(w9967cf_init_isoc(cam)<0)		return -1;		info("Isoc init complete");	info("Device opened, configuring chip ...");	if (w9967cf_init_chip(cam)<0)		return -1;	MOD_INC_USE_COUNT;	return 0;}static void w9967cf_close(struct video_device *vdev) {	w9967cfcam *cam = (w9967cfcam *)vdev;	w9967cf_deallocate_buffers(cam);		/* Clear some registers ... */	//if(w9967cf_reg_set(cam->dev, 0x0, 0xFF00)<0) return;		//if(w9967cf_reg_set(cam->dev, 0x3c, 0x0A50)<0) return;		MOD_DEC_USE_COUNT;	return;}/* * USB register, deregister */static void * __devinitw9967cf_probe(struct usb_device *dev, unsigned int ifnum,	      const struct usb_device_id *id) {	w9967cfcam *cam;	/* We don't handle multi-config cameras */	if (dev->descriptor.bNumConfigurations != 1) return NULL;	MOD_INC_USE_COUNT;	if ((cam=kmalloc(sizeof(w9967cfcam), GFP_KERNEL))==NULL)	{		printk("Couldn't get %d bytes of kernel memory", sizeof(w9967cfcam)); 		MOD_DEC_USE_COUNT;		return NULL;  	}	/* Set some constant */	cam->dev                = dev;	cam->ctrlreg.width      = 352;	cam->ctrlreg.height     = 288; 	cam->ctrlreg.ccir_clamp =   1;	cam->grabbing           =   0;	cam->alternateIface     =   1;   /* 1023, 8Mb/s. */	cam->packet_size        = wPacketSize[cam->alternateIface-1];	cam-> ctrlreg.vid_dataformat = W9967CF_YUV422_PACKED;	cam-> frame_depth = 24;			cam->saturation = cam->brightness = cam->hue = cam->colour= \	cam->contrast = cam->whiteness = 32768; /* Default values, not used yet! */	cam->urb=NULL;	cam->tbuf=NULL;		/* Set up the cam vdev structure */	memcpy(&cam->vdev, &w9967cf_vdev_template, sizeof(w9967cf_vdev_template)); /* 	if (usb_set_interface(cam->dev, 0, cam->alternateIface) < 0) { *//* 		printk("Error setting alternate interface...\n"); *//* 		return NULL; *//* 	} */	/* Try to register the device with v4l */	if (video_register_device(&cam->vdev, VFL_TYPE_GRABBER, -1) == -1) 	{ 		printk("w9967cf driver: video_register_device failed\n"); 		kfree(cam);		MOD_DEC_USE_COUNT;		return NULL;	}	info("Video Driver registered!");	MOD_DEC_USE_COUNT;	return cam;}static void __devexit w9967cf_destroy(struct usb_device *dev, void *ptr) {	w9967cfcam *cam = (w9967cfcam *)ptr;	video_unregister_device(&cam->vdev);	if (cam != NULL) kfree(cam);	return;}/* *  * Module Routines, register the driver in the kernel. * */static struct usb_driver usb_w9967cf_driver = {        name:       "Winbond 996[78]cf Webcam IC Linux driver",	id_table:   device_table,	probe:      w9967cf_probe,	disconnect: w9967cf_destroy,};#ifdef MODULE static int __init usb_w9967cf_init(void) {	if (usb_register(&usb_w9967cf_driver) < 0)		return -1;	info ("Winbond 996[78]cf driver registered");	return 0;}static void __init usb_w9968cf_destroy(void) {	usb_deregister(&usb_w9967cf_driver);	info("Winbond 996[78]cf driver deregistered");}module_init(usb_w9967cf_init);module_exit(usb_w9968cf_destroy);#endif

⌨️ 快捷键说明

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