diff -c old/pwc-if.c new/pwc-if.c
*** old/pwc-if.c	Fri Apr  1 22:17:46 2005
--- new/pwc-if.c	Sun Apr 24 09:52:32 2005
***************
*** 1,13 ****
  /* Linux driver for Philips webcam
     USB and Video4Linux interface part.
     (C) 1999-2004 Nemosoft Unv.
-    (C) 2004      Luc Saillard (luc@saillard.org)
- 
-    NOTE: this version of pwc is an unofficial (modified) release of pwc & pcwx
-    driver and thus may have bugs that are not present in the original version.
-    Please send bug reports and support requests to <luc@saillard.org>.
-    The decompression routines have been implemented by reverse-engineering the
-    Nemosoft binary pwcx module. Caveat emptor.
  
     This program is free software; you can redistribute it and/or modify
     it under the terms of the GNU General Public License as published by
--- 1,6 ----
***************
*** 62,69 ****
  #include <linux/poll.h>
  #include <linux/slab.h>
  #include <linux/vmalloc.h>
  #include <asm/io.h>
- #include <linux/moduleparam.h>
  
  #include "pwc.h"
  #include "pwc-ioctl.h"
--- 55,62 ----
  #include <linux/poll.h>
  #include <linux/slab.h>
  #include <linux/vmalloc.h>
+ #include <linux/wrapper.h>
  #include <asm/io.h>
  
  #include "pwc.h"
  #include "pwc-ioctl.h"
***************
*** 84,90 ****
  	{ USB_DEVICE(0x0471, 0x0308) },
  	{ USB_DEVICE(0x0471, 0x030C) },
  	{ USB_DEVICE(0x0471, 0x0310) },
! 	{ USB_DEVICE(0x0471, 0x0311) }, /* Philips ToUcam PRO II */
  	{ USB_DEVICE(0x0471, 0x0312) },
  	{ USB_DEVICE(0x0471, 0x0313) }, /* the 'new' 720K */
  	{ USB_DEVICE(0x069A, 0x0001) }, /* Askey */
--- 77,83 ----
  	{ USB_DEVICE(0x0471, 0x0308) },
  	{ USB_DEVICE(0x0471, 0x030C) },
  	{ USB_DEVICE(0x0471, 0x0310) },
! 	{ USB_DEVICE(0x0471, 0x0311) },
  	{ USB_DEVICE(0x0471, 0x0312) },
  	{ USB_DEVICE(0x0471, 0x0313) }, /* the 'new' 720K */
  	{ USB_DEVICE(0x069A, 0x0001) }, /* Askey */
***************
*** 109,123 ****
  };
  MODULE_DEVICE_TABLE(usb, pwc_device_table);
  
! static int usb_pwc_probe(struct usb_interface *intf, const struct usb_device_id *id);
! static void usb_pwc_disconnect(struct usb_interface *intf);
  
! static struct usb_driver pwc_driver = {
! 	.owner =		THIS_MODULE,
! 	.name =			"Philips webcam",	/* name */
! 	.id_table =		pwc_device_table,
! 	.probe =		usb_pwc_probe,		/* probe() */
! 	.disconnect =		usb_pwc_disconnect,	/* disconnect() */
  };
  
  #define MAX_DEV_HINTS	20
--- 102,116 ----
  };
  MODULE_DEVICE_TABLE(usb, pwc_device_table);
  
! static void *usb_pwc_probe(struct usb_device *udev, unsigned int ifnum, const struct usb_device_id *id);
! static void usb_pwc_disconnect(struct usb_device *udev, void *ptr);
  
! static struct usb_driver pwc_driver =
! {
! 	name:			"Philips webcam",	/* name */
! 	id_table:		pwc_device_table,
! 	probe:			usb_pwc_probe,		/* probe() */
! 	disconnect:		usb_pwc_disconnect,	/* disconnect() */
  };
  
  #define MAX_DEV_HINTS	20
***************
*** 140,172 ****
  
  /***/
  
! static int pwc_video_open(struct inode *inode, struct file *file);
! static int pwc_video_close(struct inode *inode, struct file *file);
! static ssize_t pwc_video_read(struct file *file, char __user *buf,
! 			  size_t count, loff_t *ppos);
! static unsigned int pwc_video_poll(struct file *file, poll_table *wait);
! static int  pwc_video_ioctl(struct inode *inode, struct file *file,
! 			    unsigned int ioctlnr, unsigned long arg);
! static int  pwc_video_mmap(struct file *file, struct vm_area_struct *vma);
! 
! static struct file_operations pwc_fops = {
! 	.owner =	THIS_MODULE,
! 	.open =		pwc_video_open,
! 	.release =     	pwc_video_close,
! 	.read =		pwc_video_read,
! 	.poll =		pwc_video_poll,
! 	.mmap =		pwc_video_mmap,
! 	.ioctl =        pwc_video_ioctl,
! 	.llseek =       no_llseek,
! };
  static struct video_device pwc_template = {
! 	.owner =	THIS_MODULE,
! 	.name =		"Philips Webcam",	/* Filled in later */
! 	.type =		VID_TYPE_CAPTURE,
! 	.hardware =	VID_HARDWARE_PWC,
! 	.release =	video_device_release,
! 	.fops =         &pwc_fops,
! 	.minor =        -1,
  };
  
  /***************************************************************************/
--- 133,160 ----
  
  /***/
  
! static int  pwc_video_open(struct video_device *vdev, int mode);
! static void pwc_video_close(struct video_device *vdev);
! static long pwc_video_read(struct video_device *vdev, char *buf, unsigned long count, int noblock);
! static long pwc_video_write(struct video_device *vdev, const char *buf, unsigned long count, int noblock);
! static unsigned int pwc_video_poll(struct video_device *vdev, struct file *file, poll_table *wait);
! static int  pwc_video_ioctl(struct video_device *vdev, unsigned int cmd, void *arg);
! static int  pwc_video_mmap(struct video_device *vdev, const char *adr, unsigned long size);
! 
  static struct video_device pwc_template = {
! 	owner:		THIS_MODULE,
! 	name:		"Philips Webcam",	/* Filled in later */
! 	type:		VID_TYPE_CAPTURE,
! 	hardware:	VID_HARDWARE_PWC,
! 	open:		pwc_video_open,
! 	close:		pwc_video_close,
! 	read:		pwc_video_read,
! 	write:		pwc_video_write,
! 	poll:		pwc_video_poll,
! 	ioctl:		pwc_video_ioctl,
! 	mmap:		pwc_video_mmap,
! 	initialize:	NULL,			/* initialize */
! 	minor:		0			/* minor */
  };
  
  /***************************************************************************/
***************
*** 206,212 ****
  /* Here we want the physical address of the memory.
   * This is used when initializing the contents of the area.
   */
- #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,10)
  static inline unsigned long kvirt_to_pa(unsigned long adr) 
  {
          unsigned long kva, ret;
--- 194,199 ----
***************
*** 216,259 ****
  	ret = __pa(kva);
          return ret;
  }
- #endif
  
! static void * pwc_rvmalloc(unsigned long size)
  {
  	void * mem;
  	unsigned long adr;
  
  	size=PAGE_ALIGN(size);
          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) 
! 	 {
! 	   SetPageReserved(vmalloc_to_page((void *)adr));
! 	   adr  += PAGE_SIZE;
! 	   size -= PAGE_SIZE;
! 	 }
  	return mem;
  }
  
! static void pwc_rvfree(void * mem, unsigned long size)
  {
          unsigned long adr;
  
! 	if (!mem) 
! 	  	return;
! 
! 	adr=(unsigned long) mem;
! 	while ((long) size > 0) 
! 	 {
! 	   ClearPageReserved(vmalloc_to_page((void *)adr));
! 	   adr  += PAGE_SIZE;
! 	   size -= PAGE_SIZE;
! 	 }
! 	vfree(mem);
  }
  
  
--- 203,245 ----
  	ret = __pa(kva);
          return ret;
  }
  
! static void * rvmalloc(unsigned long size)
  {
  	void * mem;
  	unsigned long adr;
  
  	size=PAGE_ALIGN(size);
          mem=vmalloc_32(size);
! 	if (mem) 
! 	{
! 		memset(mem, 0, size); /* Clear the ram out, no junk to the user */
! 	        adr=(unsigned long) mem;
! 		while (size > 0) 
!                 {
! 			mem_map_reserve(vmalloc_to_page((void *)adr));
! 			adr+=PAGE_SIZE;
! 			size-=PAGE_SIZE;
! 		}
! 	}
  	return mem;
  }
  
! static void rvfree(void * mem, unsigned long size)
  {
          unsigned long adr;
  
! 	if (mem) 
! 	{
! 	        adr=(unsigned long) mem;
! 		while ((long) size > 0) 
!                 {
! 			mem_map_unreserve(vmalloc_to_page((void *)adr));
! 			adr+=PAGE_SIZE;
! 			size-=PAGE_SIZE;
! 		}
! 		vfree(mem);
! 	}
  }
  
  
***************
*** 294,300 ****
  		pdev->fbuf = kbuf;
  		memset(kbuf, 0, default_fbufs * sizeof(struct pwc_frame_buf));
  	}
- 
  	/* create frame buffers, and make circular ring */
  	for (i = 0; i < default_fbufs; i++) {
  		if (pdev->fbuf[i].data == NULL) {
--- 280,285 ----
***************
*** 311,316 ****
--- 296,303 ----
  	
  	/* Allocate decompressor table space */
  	kbuf = NULL;
+ 
+ 
  	switch (pdev->type)
  	 {
  	  case 675:
***************
*** 336,357 ****
  	pdev->decompress_data = kbuf;
  	
  	/* Allocate image buffer; double buffer for mmap() */
! 	kbuf = pwc_rvmalloc(pwc_mbufs * PAGE_ALIGN(pdev->len_per_image));
  	if (kbuf == NULL) {
! 		Err("Failed to allocate image buffer(s). needed (%d)\n",pwc_mbufs * PAGE_ALIGN(pdev->len_per_image));
  		return -ENOMEM;
  	}
  	Trace(TRACE_MEMORY, "Allocated image buffer at %p.\n", kbuf);
  	pdev->image_data = kbuf;
! 	for (i = 0; i < pwc_mbufs; i++)
! 	{
  		pdev->images[i].bufmem = kbuf + i * PAGE_ALIGN(pdev->len_per_image);
  		pdev->images[i].vma_use_count = 0;
! 	}
  	for (; i < MAX_IMAGES; i++)
- 	{
  		pdev->images[i].bufmem = NULL;
- 	}
  
  	kbuf = NULL;
  	  
--- 323,341 ----
  	pdev->decompress_data = kbuf;
  	
  	/* Allocate image buffer; double buffer for mmap() */
! 	kbuf = rvmalloc(pwc_mbufs * PAGE_ALIGN(pdev->len_per_image));
  	if (kbuf == NULL) {
! 		Err("Failed to allocate image buffer(s).\n");
  		return -ENOMEM;
  	}
  	Trace(TRACE_MEMORY, "Allocated image buffer at %p.\n", kbuf);
  	pdev->image_data = kbuf;
! 	for (i = 0; i < pwc_mbufs; i++) {
  		pdev->images[i].bufmem = kbuf + i * PAGE_ALIGN(pdev->len_per_image);
  		pdev->images[i].vma_use_count = 0;
! 	      }
  	for (; i < MAX_IMAGES; i++)
  		pdev->images[i].bufmem = NULL;
  
  	kbuf = NULL;
  	  
***************
*** 367,372 ****
--- 351,357 ----
  
  	if (pdev == NULL)
  		return;
+ 
  	/* Release Iso-pipe buffers */
  	for (i = 0; i < MAX_ISO_BUFS; i++)
  		if (pdev->sbuf[i].data != NULL) {
***************
*** 398,404 ****
  	/* Release image buffers */
  	if (pdev->image_data != NULL) {
  		Trace(TRACE_MEMORY, "Freeing image buffer at %p.\n", pdev->image_data);
! 		pwc_rvfree(pdev->image_data, pwc_mbufs * PAGE_ALIGN(pdev->len_per_image));
  	}
  	pdev->image_data = NULL;
  	
--- 383,389 ----
  	/* Release image buffers */
  	if (pdev->image_data != NULL) {
  		Trace(TRACE_MEMORY, "Freeing image buffer at %p.\n", pdev->image_data);
! 		rvfree(pdev->image_data, pwc_mbufs * PAGE_ALIGN(pdev->len_per_image));
  	}
  	pdev->image_data = NULL;
  	
***************
*** 607,613 ****
  /* This gets called for the Isochronous pipe (video). This is done in
   * interrupt time, so it has to be fast, not crash, and not stall. Neat.
   */
! static void pwc_isoc_handler(struct urb *urb, struct pt_regs *regs)
  {
  	struct pwc_device *pdev;
  	int i, fst, flen;
--- 592,598 ----
  /* This gets called for the Isochronous pipe (video). This is done in
   * interrupt time, so it has to be fast, not crash, and not stall. Neat.
   */
! static void pwc_isoc_handler(struct urb *urb)
  {
  	struct pwc_device *pdev;
  	int i, fst, flen;
***************
*** 621,627 ****
  		Err("isoc_handler() called with NULL device?!\n");
  		return;
  	}
- 
  	if (urb->status == -ENOENT || urb->status == -ECONNRESET) {
  		Trace(TRACE_OPEN, "pwc_isoc_handler(): URB (%p) unlinked %ssynchronuously.\n", urb, urb->status == -ENOENT ? "" : "a");
  		return;
--- 606,611 ----
***************
*** 792,802 ****
  handler_end:
  	if (awake)
  		wake_up_interruptible(&pdev->frameq);
! 
! 	urb->dev = pdev->udev;
! 	i = usb_submit_urb(urb, GFP_ATOMIC);
! 	if (i != 0)
! 		Err("Error (%d) re-submitting urb in pwc_isoc_handler.\n", i);
  }
  
  
--- 776,782 ----
  handler_end:
  	if (awake)
  		wake_up_interruptible(&pdev->frameq);
! 	/* No URB resubmitting in this kernel */
  }
  
  
***************
*** 806,813 ****
  	struct urb *urb;
  	int i, j, ret;
  
! 	struct usb_interface *intf;
! 	struct usb_host_interface *idesc = NULL;
  
  	if (pdev == NULL)
  		return -EFAULT;
--- 786,792 ----
  	struct urb *urb;
  	int i, j, ret;
  
! 	struct usb_interface_descriptor *idesc;
  
  	if (pdev == NULL)
  		return -EFAULT;
***************
*** 819,847 ****
  	/* Get the current alternate interface, adjust packet size */
  	if (!udev->actconfig)
  		return -EFAULT;
! #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,5)
! 	idesc = &udev->actconfig->interface[0]->altsetting[pdev->valternate];
! #else
! 	intf = usb_ifnum_to_if(udev, 0);
! 	if (intf)
! 		idesc = usb_altnum_to_altsetting(intf, pdev->valternate);
! #endif
! 		
  	if (!idesc)
  		return -EFAULT;
  
  	/* Search video endpoint */
  	pdev->vmax_packet_size = -1;
! 	for (i = 0; i < idesc->desc.bNumEndpoints; i++) {
! 		if ((idesc->endpoint[i].desc.bEndpointAddress & 0xF) == pdev->vendpoint) {
! #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,11)
! 			pdev->vmax_packet_size = idesc->endpoint[i].desc.wMaxPacketSize;
! #else
! 			pdev->vmax_packet_size = le16_to_cpu(idesc->endpoint[i].desc.wMaxPacketSize);
! #endif
  			break;
  		}
- 	}
  	
  	if (pdev->vmax_packet_size < 0 || pdev->vmax_packet_size > ISO_MAX_FRAME_SIZE) {
  		Err("Failed to find packet size for video endpoint in current alternate setting.\n");
--- 798,814 ----
  	/* Get the current alternate interface, adjust packet size */
  	if (!udev->actconfig)
  		return -EFAULT;
! 	idesc = &udev->actconfig->interface[0].altsetting[pdev->valternate];
  	if (!idesc)
  		return -EFAULT;
  
  	/* Search video endpoint */
  	pdev->vmax_packet_size = -1;
! 	for (i = 0; i < idesc->bNumEndpoints; i++)
! 		if ((idesc->endpoint[i].bEndpointAddress & 0xF) == pdev->vendpoint) {
! 			pdev->vmax_packet_size = idesc->endpoint[i].wMaxPacketSize;
  			break;
  		}
  	
  	if (pdev->vmax_packet_size < 0 || pdev->vmax_packet_size > ISO_MAX_FRAME_SIZE) {
  		Err("Failed to find packet size for video endpoint in current alternate setting.\n");
***************
*** 856,862 ****
  		return ret;
  
  	for (i = 0; i < MAX_ISO_BUFS; i++) {
! 		urb = usb_alloc_urb(ISO_FRAMES_PER_DESC, GFP_KERNEL);
  		if (urb == NULL) {
  			Err("Failed to allocate urb %d\n", i);
  			ret = -ENOMEM;
--- 823,829 ----
  		return ret;
  
  	for (i = 0; i < MAX_ISO_BUFS; i++) {
! 		urb = usb_alloc_urb(ISO_FRAMES_PER_DESC);
  		if (urb == NULL) {
  			Err("Failed to allocate urb %d\n", i);
  			ret = -ENOMEM;
***************
*** 880,889 ****
  	for (i = 0; i < MAX_ISO_BUFS; i++) {
  		urb = pdev->sbuf[i].urb;
  
! 		urb->interval = 1; // devik
  		urb->dev = udev;
  	        urb->pipe = usb_rcvisocpipe(udev, pdev->vendpoint);
! 		urb->transfer_flags = URB_ISO_ASAP;
  	        urb->transfer_buffer = pdev->sbuf[i].data;
  	        urb->transfer_buffer_length = ISO_BUFFER_SIZE;
  	        urb->complete = pwc_isoc_handler;
--- 847,856 ----
  	for (i = 0; i < MAX_ISO_BUFS; i++) {
  		urb = pdev->sbuf[i].urb;
  
! 		urb->next = pdev->sbuf[(i + 1) % MAX_ISO_BUFS].urb;
  		urb->dev = udev;
  	        urb->pipe = usb_rcvisocpipe(udev, pdev->vendpoint);
! 		urb->transfer_flags = USB_ISO_ASAP;
  	        urb->transfer_buffer = pdev->sbuf[i].data;
  	        urb->transfer_buffer_length = ISO_BUFFER_SIZE;
  	        urb->complete = pwc_isoc_handler;
***************
*** 898,904 ****
  
  	/* link */
  	for (i = 0; i < MAX_ISO_BUFS; i++) {
! 		ret = usb_submit_urb(pdev->sbuf[i].urb, GFP_KERNEL);
  		if (ret)
  			Err("isoc_init() submit_urb %d failed with error %d\n", i, ret);
  		else
--- 865,871 ----
  
  	/* link */
  	for (i = 0; i < MAX_ISO_BUFS; i++) {
! 		ret = usb_submit_urb(pdev->sbuf[i].urb);
  		if (ret)
  			Err("isoc_init() submit_urb %d failed with error %d\n", i, ret);
  		else
***************
*** 927,933 ****
  		if (urb != 0) {
  			if (pdev->iso_init) {
  				Trace(TRACE_MEMORY, "Unlinking URB %p\n", urb);
! 				usb_kill_urb(urb);
  			}
  			Trace(TRACE_MEMORY, "Freeing URB\n");
  			usb_free_urb(urb);
--- 894,900 ----
  		if (urb != 0) {
  			if (pdev->iso_init) {
  				Trace(TRACE_MEMORY, "Unlinking URB %p\n", urb);
! 				usb_unlink_urb(urb);
  			}
  			Trace(TRACE_MEMORY, "Freeing URB\n");
  			usb_free_urb(urb);
***************
*** 980,985 ****
--- 947,953 ----
  /*********
   * sysfs
   *********/
+ #if 0
  static inline struct pwc_device *cd_to_pwc(struct class_device *cd)
  {
  	struct video_device *vdev = to_video_device(cd);
***************
*** 992,998 ****
  	return sprintf(buf, "%d %d\n", pdev->pan_angle, pdev->tilt_angle);
  }
  
! static ssize_t store_pan_tilt(struct class_device *class_dev, const char *buf,
  			 size_t count)
  {
  	struct pwc_device *pdev = cd_to_pwc(class_dev);
--- 960,966 ----
  	return sprintf(buf, "%d %d\n", pdev->pan_angle, pdev->tilt_angle);
  }
  
! //static ssize_t store_pan_tilt(struct class_device *class_dev, const char *buf,
  			 size_t count)
  {
  	struct pwc_device *pdev = cd_to_pwc(class_dev);
***************
*** 1009,1014 ****
--- 977,983 ----
  		return ret;
  	return strlen(buf);
  }
+ 
  static CLASS_DEVICE_ATTR(pan_tilt, S_IRUGO | S_IWUSR, show_pan_tilt,
  			 store_pan_tilt);
  
***************
*** 1025,1042 ****
  	if (pdev->features & FEATURE_MOTOR_PANTILT)
  		video_device_remove_file(vdev, &class_device_attr_pan_tilt);
  }
  
  /***************************************************************************/
  /* Video4Linux functions */
  
! static int pwc_video_open(struct inode *inode, struct file *file)
  {
  	int i;
- 	struct video_device *vdev = video_devdata(file);
  	struct pwc_device *pdev;
  
  	Trace(TRACE_OPEN, ">> video_open called(vdev = 0x%p).\n", vdev);
  	
  	pdev = (struct pwc_device *)vdev->priv;
  	if (pdev == NULL)
  		BUG();
--- 994,1014 ----
  	if (pdev->features & FEATURE_MOTOR_PANTILT)
  		video_device_remove_file(vdev, &class_device_attr_pan_tilt);
  }
+ #endif
+ 
  
  /***************************************************************************/
  /* Video4Linux functions */
  
! static int pwc_video_open(struct video_device *vdev, int mode)
  {
  	int i;
  	struct pwc_device *pdev;
  
  	Trace(TRACE_OPEN, ">> video_open called(vdev = 0x%p).\n", vdev);
  	
+ 	if (vdev == NULL)
+ 		BUG();
  	pdev = (struct pwc_device *)vdev->priv;
  	if (pdev == NULL)
  		BUG();
***************
*** 1047,1054 ****
  	if (!pdev->usb_init) {
  		Trace(TRACE_OPEN, "Doing first time initialization.\n");
  		pdev->usb_init = 1;
! 		
! 		if (pwc_trace & TRACE_OPEN)
  		{
  			/* Query sensor type */
  			const char *sensor_type = NULL;
--- 1019,1026 ----
  	if (!pdev->usb_init) {
  		Trace(TRACE_OPEN, "Doing first time initialization.\n");
  		pdev->usb_init = 1;
! 
! 		if (pwc_trace & TRACE_OPEN)		
  		{
  			/* Query sensor type */
  			const char *sensor_type = NULL;
***************
*** 1085,1091 ****
  	/* Set LED on/off time */
  	if (pwc_set_leds(pdev, led_on, led_off) < 0)
  		Info("Failed to set LED on/off time.\n");
! 	
  	pwc_construct(pdev); /* set min/max sizes correct */
  
  	/* So far, so good. Allocate memory. */
--- 1057,1063 ----
  	/* Set LED on/off time */
  	if (pwc_set_leds(pdev, led_on, led_off) < 0)
  		Info("Failed to set LED on/off time.\n");
! 
  	pwc_construct(pdev); /* set min/max sizes correct */
  
  	/* So far, so good. Allocate memory. */
***************
*** 1139,1154 ****
  	}
  
  	pdev->vopen++;
- 	file->private_data = vdev;
  	up(&pdev->modlock);
  	Trace(TRACE_OPEN, "<< video_open() returns 0.\n");
  	return 0;
  }
  
  /* Note that all cleanup is done in the reverse order as in _open */
! static int pwc_video_close(struct inode *inode, struct file *file)
  {
- 	struct video_device *vdev = file->private_data;
  	struct pwc_device *pdev;
  	int i;
  
--- 1111,1124 ----
  	}
  
  	pdev->vopen++;
  	up(&pdev->modlock);
  	Trace(TRACE_OPEN, "<< video_open() returns 0.\n");
  	return 0;
  }
  
  /* Note that all cleanup is done in the reverse order as in _open */
! static void pwc_video_close(struct video_device *vdev)
  {
  	struct pwc_device *pdev;
  	int i;
  
***************
*** 1198,1204 ****
  	}
  	pdev->vopen = 0;
  	Trace(TRACE_OPEN, "<< video_close()\n");
- 	return 0;
  }
  
  /*
--- 1168,1173 ----
***************
*** 1213,1228 ****
                  device is tricky anyhow.
   */
  
! static ssize_t pwc_video_read(struct file *file, char __user *buf,
! 			  size_t count, loff_t *ppos)
  {
- 	struct video_device *vdev = file->private_data;
  	struct pwc_device *pdev;
- 	int noblock = file->f_flags & O_NONBLOCK;
  	DECLARE_WAITQUEUE(wait, current);
          int bytes_to_read;
  
! 	Trace(TRACE_READ, "pwc_video_read(vdev=0x%p, buf=%p, count=%ld) called.\n", vdev, buf, count);
  	if (vdev == NULL)
  		return -EFAULT;
  	pdev = vdev->priv;
--- 1182,1194 ----
                  device is tricky anyhow.
   */
  
! static long pwc_video_read(struct video_device *vdev, char *buf, unsigned long count, int noblock)
  {
  	struct pwc_device *pdev;
  	DECLARE_WAITQUEUE(wait, current);
          int bytes_to_read;
  
! 	Trace(TRACE_READ, "video_read(0x%p, %p, %ld, %d) called.\n", vdev, buf, count, noblock);
  	if (vdev == NULL)
  		return -EFAULT;
  	pdev = vdev->priv;
***************
*** 1257,1263 ****
  		}
  		remove_wait_queue(&pdev->frameq, &wait);
  		set_current_state(TASK_RUNNING);
!                                                                                                                                                                                 
  		/* Decompress and release frame */
  		if (pwc_handle_frame(pdev))
  			return -EFAULT;
--- 1223,1229 ----
  		}
  		remove_wait_queue(&pdev->frameq, &wait);
  		set_current_state(TASK_RUNNING);
! 
  		/* Decompress and release frame */
  		if (pwc_handle_frame(pdev))
  			return -EFAULT;
***************
*** 1282,1290 ****
  	return count;
  }
  
! static unsigned int pwc_video_poll(struct file *file, poll_table *wait)
  {
- 	struct video_device *vdev = file->private_data;
  	struct pwc_device *pdev;
  
  	if (vdev == NULL)
--- 1248,1261 ----
  	return count;
  }
  
! 
! static long pwc_video_write(struct video_device *vdev, const char *buf, unsigned long count, int noblock)
! {
! 	return -EINVAL;
! }
! 
! static unsigned int pwc_video_poll(struct video_device *vdev, struct file *file, poll_table *wait)
  {
  	struct pwc_device *pdev;
  
  	if (vdev == NULL)
***************
*** 1302,1312 ****
  	return 0;
  }
  
! static int pwc_video_ioctl(struct inode *inode, struct file *file,
! 			   unsigned int cmd, unsigned long arg)
  {
! 	return video_usercopy(inode, file, cmd, arg, pwc_video_do_ioctl);
! }
  
  static void pwc_vm_open(struct vm_area_struct* vma)
  {       
--- 1273,1663 ----
  	return 0;
  }
  
! static int pwc_video_ioctl(struct video_device *vdev, unsigned int cmd, void *arg)
  {
! 	struct pwc_device *pdev;
! 	DECLARE_WAITQUEUE(wait, current);
! 
! 	if (vdev == NULL)
! 		return -EFAULT;
! 	pdev = vdev->priv;
! 	if (pdev == NULL)
! 		return -EFAULT;
! 
! 	switch (cmd) {
! 		/* Query cabapilities */
! 		case VIDIOCGCAP:
! 		{
! 			struct video_capability caps;
! 
! 			strcpy(caps.name, vdev->name);
! 			caps.type = VID_TYPE_CAPTURE;
! 			caps.channels = 1;
! 			caps.audios = 1;
! 			caps.minwidth  = pdev->view_min.x;
! 			caps.minheight = pdev->view_min.y;
! 			caps.maxwidth  = pdev->view_max.x;
! 			caps.maxheight = pdev->view_max.y;
! 			if (copy_to_user(arg, &caps, sizeof(caps)))
! 				return -EFAULT;
! 			break;
! 		}
! 
! 		/* Channel functions (simulate 1 channel) */
! 		case VIDIOCGCHAN:
! 		{
! 			struct video_channel v;
! 
! 			if (copy_from_user(&v, arg, sizeof(v)))
! 				return -EFAULT;
! 			if (v.channel != 0)
! 				return -EINVAL;
! 
! 			v.flags = 0;
! 			v.tuners = 0;
! 			v.type = VIDEO_TYPE_CAMERA;
! 			strcpy(v.name, "Webcam");
! 
! 			if (copy_to_user(arg, &v, sizeof(v)))
! 				return -EFAULT;
! 
! 			return 0;
! 		}
! 
! 		case VIDIOCSCHAN:
! 		{
! 			/* The spec says the argument is an integer, but
! 			   the bttv driver uses a video_channel arg, which
! 			   makes sense becasue it also has the norm flag.
! 			 */
! 			struct video_channel v;
! 
! 			if (copy_from_user(&v, arg, sizeof(v)))
! 				return -EFAULT;
! 
! 			if (v.channel != 0)
! 				return -EINVAL;
! 
! 			return 0;
! 		}
! 
! 
! 		/* Picture functions; contrast etc. */
! 		case VIDIOCGPICT:
! 		{
! 			struct video_picture p;
! 			int val;
! 
! 			val = pwc_get_brightness(pdev);
! 			if (val >= 0)
! 				p.brightness = val;
! 			else
! 				p.brightness = 0xffff;
! 			val = pwc_get_contrast(pdev);
! 			if (val >= 0)
! 				p.contrast = val;
! 			else
! 				p.contrast = 0xffff;
! 			/* Gamma, Whiteness, what's the difference? :) */
! 			val = pwc_get_gamma(pdev);
! 			if (val >= 0)
! 				p.whiteness = val;
! 			else
! 				p.whiteness = 0xffff;
! 			val = pwc_get_saturation(pdev);
! 			if (val >= 0)
! 				p.colour = val;
! 			else
! 				p.colour = 0xffff;
! 			p.depth = 24;
! 			p.palette = pdev->vpalette;
! 			p.hue = 0xFFFF; /* N/A */
! 
! 			if (copy_to_user(arg, &p, sizeof(p)))
! 				return -EFAULT;
! 			break;
! 		}
! 		
! 		case VIDIOCSPICT:
! 		{
! 			struct video_picture p;
! 
! 			if (copy_from_user(&p, arg, sizeof(p)))
! 				return -EFAULT;
! 
! 			/*
! 			 *	FIXME:	Suppose we are mid read
! 			        ANSWER: No problem: the firmware of the camera
! 			                can handle brightness/contrast/etc
! 			                changes at _any_ time, and the palette
! 			                is used exactly once in the uncompress
! 			                routine.
! 			 */
! 			pwc_set_brightness(pdev, p.brightness);
! 			pwc_set_contrast(pdev, p.contrast);
! 			pwc_set_gamma(pdev, p.whiteness);
! 			pwc_set_saturation(pdev, p.colour);
!                         if (p.palette && p.palette != pdev->vpalette) {
! 				switch (p.palette) {
! 					case VIDEO_PALETTE_YUV420P:
! 					case VIDEO_PALETTE_RAW:
! 						pdev->vpalette = p.palette;
! 						return pwc_try_video_mode(pdev, pdev->image.x, pdev->image.y, pdev->vframes, pdev->vcompression, pdev->vsnapshot);
! 						break;
! 					default:
! 						return -EINVAL;
! 						break;
!       				}
! 			}
! 			break;
! 		}
! 
! 		/* Window/size parameters */		
! 		case VIDIOCGWIN:
! 		{
! 			struct video_window vw;
! 			
! 			vw.x = 0;
! 			vw.y = 0;
! 			vw.width = pdev->view.x;
! 			vw.height = pdev->view.y;
! 			vw.chromakey = 0;
! 			vw.flags = (pdev->vframes << PWC_FPS_SHIFT) | 
! 			           (pdev->vsnapshot ? PWC_FPS_SNAPSHOT : 0);
! 			
! 			if (copy_to_user(arg, &vw, sizeof(vw)))
! 				return -EFAULT;			
! 			break;
! 		}
! 		
! 		case VIDIOCSWIN:
! 		{
! 			struct video_window vw;
! 			int fps, snapshot, ret;
! 		
! 			if (copy_from_user(&vw, arg, sizeof(vw)))
! 				return -EFAULT;
! 
! 			fps = (vw.flags & PWC_FPS_FRMASK) >> PWC_FPS_SHIFT;
! 			snapshot = vw.flags & PWC_FPS_SNAPSHOT;
! 			if (fps == 0)
! 				fps = pdev->vframes;
! 			if (pdev->view.x == vw.width && pdev->view.y && fps == pdev->vframes && snapshot == pdev->vsnapshot)
! 				return 0;
! 			ret = pwc_try_video_mode(pdev, vw.width, vw.height, fps, pdev->vcompression, snapshot);
! 			if (ret)
! 				return ret;
! 			break;		
! 		}
! 		
! 		/* We don't have overlay support (yet) */
! 		case VIDIOCGFBUF:
! 		{
! 			struct video_buffer vb;
! 
! 			vb.base = NULL;
! 			vb.height = 0;
! 			vb.width = 0;
! 			vb.depth = 0;
! 			vb.bytesperline = 0;
! 			
! 			if (copy_to_user((void *)arg, (void *)&vb, sizeof(vb)))
! 				return -EFAULT;
! 			break;
! 		}
! 
! 		/* mmap() functions */
! 		case VIDIOCGMBUF:
! 		{
! 			/* Tell the user program how much memory is needed for a mmap() */
! 			struct video_mbuf vm;
! 			int i;
! 
! 			memset(&vm, 0, sizeof(vm));
! 			vm.size = pwc_mbufs * pdev->len_per_image;
! 			vm.frames = pwc_mbufs; /* double buffering should be enough for most applications */
! 			for (i = 0; i < pwc_mbufs; i++)
! 				vm.offsets[i] = i * pdev->len_per_image;
! 
! 			if (copy_to_user((void *)arg, (void *)&vm, sizeof(vm)))
! 				return -EFAULT;
! 			break;
! 		}
! 
! 		case VIDIOCMCAPTURE:
! 		{
! 			/* Start capture into a given image buffer (called 'frame' in video_mmap structure) */
! 			struct video_mmap vm;
! 
! 			if (copy_from_user((void *)&vm, (void *)arg, sizeof(vm)))
! 				return -EFAULT;
! 			Trace(TRACE_READ, "VIDIOCMCAPTURE: %dx%d, frame %d, format %d\n", vm.width, vm.height, vm.frame, vm.format);
! 			if (vm.frame < 0 || vm.frame >= pwc_mbufs)
! 				return -EINVAL;
! 
! 			/* xawtv is nasty. It probes the available palettes
! 			   by setting a very small image size and trying
! 			   various palettes... The driver doesn't support
! 			   such small images, so I'm working around it.
! 			 */
! 			if (vm.format)
! 			{
! 				switch (vm.format)
! 				{
! 					case VIDEO_PALETTE_YUV420P:
! 					case VIDEO_PALETTE_RAW:
! 						break;
! 					default:
! 						return -EINVAL;
! 						break;
! 				}
! 			}
! 
! 			if ((vm.width != pdev->view.x || vm.height != pdev->view.y) &&
! 			    (vm.width >= pdev->view_min.x && vm.height >= pdev->view_min.y)) {
! 				int ret;
! 
! 				Trace(TRACE_OPEN, "VIDIOCMCAPTURE: changing size to please xawtv :-(.\n");
! 				ret = pwc_try_video_mode(pdev, vm.width, vm.height, pdev->vframes, pdev->vcompression, pdev->vsnapshot);
! 				if (ret)
! 					return ret;
! 			} /* ... size mismatch */
! 
! 			/* FIXME: should we lock here? */
! 			if (pdev->image_used[vm.frame])
! 				return -EBUSY;	/* buffer wasn't available. Bummer */
! 			pdev->image_used[vm.frame] = 1;
! 
! 			/* Okay, we're done here. In the SYNC call we wait until a 
! 			   frame comes available, then expand image into the given 
! 			   buffer.
! 			   In contrast to the CPiA cam the Philips cams deliver a
! 			   constant stream, almost like a grabber card. Also,
! 			   we have separate buffers for the rawdata and the image,
! 			   meaning we can nearly always expand into the requested buffer.
! 			 */
! 			Trace(TRACE_READ, "VIDIOCMCAPTURE done.\n");
! 			break;
! 		}
! 
! 		case VIDIOCSYNC:
! 		{
! 			/* The doc says: "Whenever a buffer is used it should
! 			   call VIDIOCSYNC to free this frame up and continue."
! 			   
! 			   The only odd thing about this whole procedure is 
! 			   that MCAPTURE flags the buffer as "in use", and
! 			   SYNC immediately unmarks it, while it isn't 
! 			   after SYNC that you know that the buffer actually
! 			   got filled! So you better not start a CAPTURE in
! 			   the same frame immediately (use double buffering). 
! 			   This is not a problem for this cam, since it has 
! 			   extra intermediate buffers, but a hardware 
! 			   grabber card will then overwrite the buffer 
! 			   you're working on.
! 			 */
! 			int mbuf, ret;
! 
! 			if (copy_from_user((void *)&mbuf, arg, sizeof(int)))
! 				return -EFAULT;
! 
! 			Trace(TRACE_READ, "VIDIOCSYNC called (%d).\n", mbuf);
! 
! 			/* bounds check */
! 			if (mbuf < 0 || mbuf >= pwc_mbufs)
! 				return -EINVAL;
! 			/* check if this buffer was requested anyway */
! 			if (pdev->image_used[mbuf] == 0)
! 				return -EINVAL;
! 
! 			/* Add ourselves to the frame wait-queue.
! 			   In the loop, check for error conditions and signals.
! 
! 			   FIXME: needs auditing for safety.
! 			   QUESTION: In what respect? I think that using the
! 			             frameq is safe now.
! 			 */
! 			add_wait_queue(&pdev->frameq, &wait);
! 			while (pdev->full_frames == NULL) {
! 				if (pdev->error_status) {
! 					remove_wait_queue(&pdev->frameq, &wait);
! 					set_current_state(TASK_RUNNING);
! 					return -pdev->error_status;
! 				}
! 	                	if (signal_pending(current)) {
! 	                		remove_wait_queue(&pdev->frameq, &wait);
! 		                	set_current_state(TASK_RUNNING);
! 		                	return -ERESTARTSYS;
! 	        	        }
! 	                	schedule();
! 		                set_current_state(TASK_INTERRUPTIBLE);
! 			}
! 			remove_wait_queue(&pdev->frameq, &wait);
! 			set_current_state(TASK_RUNNING);
! 				
! 			/* The frame is ready. Expand in the image buffer 
! 			   requested by the user. I don't care if you 
! 			   mmap() 5 buffers and request data in this order: 
! 			   buffer 4 2 3 0 1 2 3 0 4 3 1 . . .
! 			   Grabber hardware may not be so forgiving.
! 			 */
! 			Trace(TRACE_READ, "VIDIOCSYNC: frame ready.\n");
! 			pdev->fill_image = mbuf; /* tell in which buffer we want the image to be expanded */
! 			/* Decompress, etc */
! 			ret = pwc_handle_frame(pdev);
! 			pdev->image_used[mbuf] = 0;
! 			if (ret)
! 				return -EFAULT;
! 			break;
! 		}
! 		
! 		case VIDIOCGAUDIO:
! 		{
! 			struct video_audio v;
! 			
! 			strcpy(v.name, "Microphone");
! 			v.audio = -1; /* unknown audio minor */
! 			v.flags = 0;
! 			v.mode = VIDEO_SOUND_MONO;
! 			v.volume = 0;
! 			v.bass = 0;
! 			v.treble = 0;
! 			v.balance = 0x8000;
! 			v.step = 1;
! 			
! 			if (copy_to_user(arg, &v, sizeof(v)))
! 				return -EFAULT;
! 			break;	
! 		}
! 		
! 		case VIDIOCSAUDIO:
! 		{
! 			struct video_audio v;
! 			
! 			if (copy_from_user(&v, arg, sizeof(v)))
! 				return -EFAULT;
! 			/* Dummy: nothing can be set */
! 			break;
! 		}
! 		
! 		case VIDIOCGUNIT:
! 		{
! 			struct video_unit vu;
! 			
! 			vu.video = pdev->vdev->minor & 0x3F;
! 			vu.audio = -1; /* not known yet */
! 			vu.vbi = -1;
! 			vu.radio = -1;
! 			vu.teletext = -1;
! 			if (copy_to_user(arg, &vu, sizeof(vu)))
! 				return -EFAULT;
! 			break;
! 		}
! 		default:
! 			return pwc_ioctl(pdev, cmd, arg);
! 	} /* ..switch */
! 	return 0;
! }	
  
  static void pwc_vm_open(struct vm_area_struct* vma)
  {       
***************
*** 1330,1368 ****
          .close = pwc_vm_close,
  };
  
! static int pwc_video_mmap(struct file *file, struct vm_area_struct *vma)
  {
- 	struct video_device *vdev = file->private_data;
  	struct pwc_device *pdev;
! 	unsigned long start = vma->vm_start;
! 	unsigned long size  = vma->vm_end-vma->vm_start;
  	unsigned long page, pos;
  	int index;
  	
! 	Trace(TRACE_MEMORY, "mmap(0x%p, 0x%lx, %lu) called.\n", vdev, start, size);
  	pdev = vdev->priv;
- 
  	/* Find the idx buffer for this mapping */
- 	for (index = 0; index < pwc_mbufs; index++) {
- 		if (((index*PAGE_ALIGN(pdev->len_per_image))>>PAGE_SHIFT) == vma->vm_pgoff)
- 			break;
- 	}
- 	if (index == MAX_IMAGES)
- 		return -EINVAL;
  
! 	vma->vm_flags |= VM_IO;	/* from 2.6.9-acX */
  
  	pos = (unsigned long)pdev->image_data;
  	while (size > 0) {
- #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,10)
  		page = kvirt_to_pa(pos);
! 		if (remap_page_range(vma, start, page, PAGE_SIZE, PAGE_SHARED))
! 			return -EAGAIN;
! #else
! 		page = vmalloc_to_pfn((void *)pos);
! 		if (remap_pfn_range(vma, start, page, PAGE_SIZE, PAGE_SHARED))
  			return -EAGAIN;
! #endif
  		start += PAGE_SIZE;
  		pos += PAGE_SIZE;
  		if (size > PAGE_SIZE)
--- 1681,1713 ----
          .close = pwc_vm_close,
  };
  
! static int pwc_video_mmap(struct video_device *vdev, const char *adr, unsigned long size)
  {
  	struct pwc_device *pdev;
! 	unsigned long start = (unsigned long)adr;
  	unsigned long page, pos;
  	int index;
  	
! 	Trace(TRACE_MEMORY, "mmap(0x%p, 0x%p, %lu) called.\n", vdev, adr, size);
  	pdev = vdev->priv;
  	/* Find the idx buffer for this mapping */
  
! 	index=0;
! //	for (index = 0; index < pwc_mbufs; index++) {
! //		if (((index*PAGE_ALIGN(pdev->len_per_image))>>PAGE_SHIFT) == vma->vm_pgoff)
! //			break;
! //	}
! //	if (index == MAX_IMAGES)
! //		return -EINVAL;
! 
! //	vma->vm_flags |= VM_IO;	/* from 2.6.9-acX */
  
  	pos = (unsigned long)pdev->image_data;
  	while (size > 0) {
  		page = kvirt_to_pa(pos);
! 		if (remap_page_range(start, page, PAGE_SIZE, PAGE_SHARED))
  			return -EAGAIN;
! 
  		start += PAGE_SIZE;
  		pos += PAGE_SIZE;
  		if (size > PAGE_SIZE)
***************
*** 1370,1375 ****
--- 1715,1721 ----
  		else
  			size = 0;
  	}
+ 
  	return 0;
  }
  
***************
*** 1380,1388 ****
   * is loaded.
   */
  
! static int usb_pwc_probe(struct usb_interface *intf, const struct usb_device_id *id)
  {
- 	struct usb_device *udev = interface_to_usbdev(intf);
  	struct pwc_device *pdev = NULL;
  	int vendor_id, product_id, type_id;
  	int i, hint;
--- 1726,1733 ----
   * is loaded.
   */
  
! static void *usb_pwc_probe(struct usb_device *udev, unsigned int ifnum, const struct usb_device_id *id)
  {
  	struct pwc_device *pdev = NULL;
  	int vendor_id, product_id, type_id;
  	int i, hint;
***************
*** 1390,1414 ****
  	int video_nr = -1; /* default: use next available device */
  	char serial_number[30], *name;
  
- #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,11)
  	vendor_id = udev->descriptor.idVendor;
  	product_id = udev->descriptor.idProduct;
- #else
- 	vendor_id = le16_to_cpu(udev->descriptor.idVendor);
- 	product_id = le16_to_cpu(udev->descriptor.idProduct);
- #endif
  
  	/* Check if we can handle this device */
! 	Trace(TRACE_PROBE, "probe() called [%04X %04X], if %d\n", 
! 		vendor_id, product_id,
! 		intf->altsetting->desc.bInterfaceNumber);
  
  	/* the interfaces are probed one by one. We are only interested in the
  	   video interface (0) now.
  	   Interface 1 is the Audio Control, and interface 2 Audio itself.
  	 */
! 	if (intf->altsetting->desc.bInterfaceNumber > 0)
! 		return -ENODEV;
  
  	if (vendor_id == 0x0471) {
  		switch (product_id) {
--- 1735,1752 ----
  	int video_nr = -1; /* default: use next available device */
  	char serial_number[30], *name;
  
  	vendor_id = udev->descriptor.idVendor;
  	product_id = udev->descriptor.idProduct;
  
  	/* Check if we can handle this device */
! 	Trace(TRACE_PROBE, "probe() called [%04X %04X], if %d\n", udev->descriptor.idVendor, udev->descriptor.idProduct, ifnum);
  
  	/* the interfaces are probed one by one. We are only interested in the
  	   video interface (0) now.
  	   Interface 1 is the Audio Control, and interface 2 Audio itself.
  	 */
! 	if (ifnum > 0) 
! 		return NULL;
  
  	if (vendor_id == 0x0471) {
  		switch (product_id) {
***************
*** 1459,1469 ****
  			break;
  		case 0x0313:
  			Info("Philips PCVC720K/40 (ToUCam XS) USB webcam detected.\n");
! 			name = "Philips 720K/40 webcam";
  			type_id = 720;
  			break;
  		default:
! 			return -ENODEV;
  			break;
  		}
  	}
--- 1797,1807 ----
  			break;
  		case 0x0313:
  			Info("Philips PCVC720K/40 (ToUCam XS) USB webcam detected.\n");
! 			name = "Philips 720 webcam";
  			type_id = 720;
  			break;
  		default:
! 			return NULL;
  			break;
  		}
  	}
***************
*** 1475,1481 ****
  			type_id = 645;
  			break;
  		default:
! 			return -ENODEV;
  			break;
  		}
  	}
--- 1813,1819 ----
  			type_id = 645;
  			break;
  		default:
! 			return NULL;
  			break;
  		}
  	}
***************
*** 1487,1493 ****
  			type_id = 740; /* CCD sensor */
  			break;
  		case 0x08b1:
! 			Info("Logitech QuickCam Notebook Pro USB webcam detected.\n");
  			name = "Logitech QuickCam Notebook Pro";
  			type_id = 740; /* CCD sensor */
  			break;
--- 1825,1831 ----
  			type_id = 740; /* CCD sensor */
  			break;
  		case 0x08b1:
! 			Info("Logitech QuickCam for Notebook Pro USB webcam detected.\n");
  			name = "Logitech QuickCam Notebook Pro";
  			type_id = 740; /* CCD sensor */
  			break;
***************
*** 1520,1526 ****
  			type_id = 730; /* Assuming CMOS */
  			break;
          	default:
! 			return -ENODEV;
          		break;
          	}
          }
--- 1858,1864 ----
  			type_id = 730; /* Assuming CMOS */
  			break;
          	default:
!         		return NULL;
          		break;
          	}
          }
***************
*** 1533,1547 ****
  		case 0x9000:
  			Info("Samsung MPC-C10 USB webcam detected.\n");
  			name = "Samsung MPC-C10";
! 			type_id = 675;
  			break;
  		case 0x9001:
  			Info("Samsung MPC-C30 USB webcam detected.\n");
  			name = "Samsung MPC-C30";
! 			type_id = 675;
  			break;
  		default:
! 			return -ENODEV;
  			break;
  		}
  	}
--- 1871,1885 ----
  		case 0x9000:
  			Info("Samsung MPC-C10 USB webcam detected.\n");
  			name = "Samsung MPC-C10";
! 			type_id = 730;
  			break;
  		case 0x9001:
  			Info("Samsung MPC-C30 USB webcam detected.\n");
  			name = "Samsung MPC-C30";
! 			type_id = 740;
  			break;
  		default:
! 			return NULL;
  			break;
  		}
  	}
***************
*** 1558,1564 ****
  			type_id = 740;
  			break;
  		default:
! 			return -ENODEV;
  			break;
  		}
  	}
--- 1896,1902 ----
  			type_id = 740;
  			break;
  		default:
! 			return NULL;
  			break;
  		}
  	}
***************
*** 1570,1576 ****
  			type_id = 730;
  			break;
  		default:
! 			return -ENODEV;
  			break;
  		}
  	}
--- 1908,1914 ----
  			type_id = 730;
  			break;
  		default:
! 			return NULL;
  			break;
  		}
  	}
***************
*** 1583,1589 ****
  			type_id = 750;
  			break;
  		default:
! 			return -ENODEV;
  			break;
  		}
  	
--- 1921,1927 ----
  			type_id = 750;
  			break;
  		default:
! 			return NULL;
  			break;
  		}
  	
***************
*** 1601,1612 ****
  			type_id = 730; /* CMOS sensor */
  			break;
  		default:
! 			return -ENODEV;
  			break;
  		}
  	}
  	else 
! 		return -ENODEV; /* Not any of the know types; but the list keeps growing. */
  
  	memset(serial_number, 0, 30);
  	usb_string(udev, udev->descriptor.iSerialNumber, serial_number, 29);
--- 1939,1950 ----
  			type_id = 730; /* CMOS sensor */
  			break;
  		default:
! 			return NULL;
  			break;
  		}
  	}
  	else 
! 		return NULL; /* Not any of the know types; but the list keeps growing. */
  
  	memset(serial_number, 0, 30);
  	usb_string(udev, udev->descriptor.iSerialNumber, serial_number, 29);
***************
*** 1619,1625 ****
  	pdev = kmalloc(sizeof(struct pwc_device), GFP_KERNEL);
  	if (pdev == NULL) {
  		Err("Oops, could not allocate memory for pwc_device.\n");
! 		return -ENOMEM;
  	}
  	memset(pdev, 0, sizeof(struct pwc_device));
  	pdev->type = type_id;
--- 1957,1963 ----
  	pdev = kmalloc(sizeof(struct pwc_device), GFP_KERNEL);
  	if (pdev == NULL) {
  		Err("Oops, could not allocate memory for pwc_device.\n");
! 		return NULL;
  	}
  	memset(pdev, 0, sizeof(struct pwc_device));
  	pdev->type = type_id;
***************
*** 1646,1670 ****
  	init_waitqueue_head(&pdev->frameq);
  	pdev->vcompression = pwc_preferred_compression;
  
! 	/* Allocate video_device structure */
! 	pdev->vdev = video_device_alloc();
  	if (pdev->vdev == 0)
  	{
  		Err("Err, cannot allocate video_device struture. Failing probe.");
  		kfree(pdev);
! 		return -ENOMEM;
  	}
  	memcpy(pdev->vdev, &pwc_template, sizeof(pwc_template));
! 	pdev->vdev->dev = &(udev->dev);
  	strcpy(pdev->vdev->name, name);
! 	pdev->vdev->owner = THIS_MODULE;
! 	video_set_drvdata(pdev->vdev, pdev);
  
- #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,11)
  	pdev->release = udev->descriptor.bcdDevice;
- #else
- 	pdev->release = le16_to_cpu(udev->descriptor.bcdDevice);
- #endif
  	Trace(TRACE_PROBE, "Release: %04x\n", pdev->release);
  
  	/* Now search device_hint[] table for a match, so we can hint a node number. */
--- 1984,2003 ----
  	init_waitqueue_head(&pdev->frameq);
  	pdev->vcompression = pwc_preferred_compression;
  
! 	pdev->vdev = kmalloc(sizeof(struct video_device), GFP_KERNEL);
  	if (pdev->vdev == 0)
  	{
  		Err("Err, cannot allocate video_device struture. Failing probe.");
  		kfree(pdev);
! 		return NULL;
  	}
  	memcpy(pdev->vdev, &pwc_template, sizeof(pwc_template));
! //	pdev->vdev->dev = &(udev->dev);
  	strcpy(pdev->vdev->name, name);
! 	SET_MODULE_OWNER(pdev->vdev);
! 	pdev->vdev->priv = pdev;
  
  	pdev->release = udev->descriptor.bcdDevice;
  	Trace(TRACE_PROBE, "Release: %04x\n", pdev->release);
  
  	/* Now search device_hint[] table for a match, so we can hint a node number. */
***************
*** 1681,1728 ****
  		}
  	}
  
- 	pdev->vdev->release = video_device_release;
  	i = video_register_device(pdev->vdev, VFL_TYPE_GRABBER, video_nr);
  	if (i < 0) {
  		Err("Failed to register as video device (%d).\n", i);
! 		video_device_release(pdev->vdev); /* Drip... drip... drip... */
  		kfree(pdev); /* Oops, no memory leaks please */
! 		return -EIO;
  	}
  	else {
  		Info("Registered as /dev/video%d.\n", pdev->vdev->minor & 0x3F);
  	}
- 
  	/* occupy slot */
  	if (hint < MAX_DEV_HINTS) 
  		device_hint[hint].pdev = pdev;
  
  	Trace(TRACE_PROBE, "probe() function returning struct at 0x%p.\n", pdev);
! 	usb_set_intfdata (intf, pdev);
! 	pwc_create_sysfs_files(pdev->vdev);
! 	return 0;
  }
  
  /* The user janked out the cable... */
! static void usb_pwc_disconnect(struct usb_interface *intf)
  {
  	struct pwc_device *pdev;
  	int hint;
  
  	lock_kernel();
! 	pdev = usb_get_intfdata (intf);
! 	usb_set_intfdata (intf, NULL);
  	if (pdev == NULL) {
  		Err("pwc_disconnect() Called without private pointer.\n");
! 		goto disconnect_out;
  	}
  	if (pdev->udev == NULL) {
  		Err("pwc_disconnect() already called for %p\n", pdev);
! 		goto disconnect_out;
  	}
! 	if (pdev->udev != interface_to_usbdev(intf)) {
  		Err("pwc_disconnect() Woops: pointer mismatch udev/pdev.\n");
! 		goto disconnect_out;
  	}
  
  	/* We got unplugged; this is signalled by an EPIPE error code */
--- 2014,2060 ----
  		}
  	}
  
  	i = video_register_device(pdev->vdev, VFL_TYPE_GRABBER, video_nr);
  	if (i < 0) {
  		Err("Failed to register as video device (%d).\n", i);
! 		kfree(pdev->vdev); /* Drip... drip... drip... */
  		kfree(pdev); /* Oops, no memory leaks please */
! 		return NULL;
  	}
  	else {
  		Info("Registered as /dev/video%d.\n", pdev->vdev->minor & 0x3F);
  	}
  	/* occupy slot */
  	if (hint < MAX_DEV_HINTS) 
  		device_hint[hint].pdev = pdev;
  
  	Trace(TRACE_PROBE, "probe() function returning struct at 0x%p.\n", pdev);
! //	pwc_create_sysfs_files(pdev->vdev);
! 	return pdev;
  }
  
  /* The user janked out the cable... */
! static void usb_pwc_disconnect(struct usb_device *udev, void *ptr)
  {
  	struct pwc_device *pdev;
  	int hint;
  
  	lock_kernel();
! 	pdev = (struct pwc_device *)ptr;
  	if (pdev == NULL) {
  		Err("pwc_disconnect() Called without private pointer.\n");
! 		unlock_kernel();
! 		return;
  	}
  	if (pdev->udev == NULL) {
  		Err("pwc_disconnect() already called for %p\n", pdev);
! 		unlock_kernel();
! 		return;
  	}
! 	if (pdev->udev != udev) {
  		Err("pwc_disconnect() Woops: pointer mismatch udev/pdev.\n");
! 		unlock_kernel();
! 		return;
  	}
  
  	/* We got unplugged; this is signalled by an EPIPE error code */
***************
*** 1738,1750 ****
  		schedule();
  	/* Device is now closed, so we can safely unregister it */
  	Trace(TRACE_PROBE, "Unregistering video device in disconnect().\n");
! 	pwc_remove_sysfs_files(pdev->vdev);
  	video_unregister_device(pdev->vdev);
  
  	/* Free memory (don't set pdev to 0 just yet) */
  	kfree(pdev);
  
- disconnect_out:
  	/* search device_hint[] table if we occupy a slot, by any chance */
  	for (hint = 0; hint < MAX_DEV_HINTS; hint++)
  		if (device_hint[hint].pdev == pdev)
--- 2070,2082 ----
  		schedule();
  	/* Device is now closed, so we can safely unregister it */
  	Trace(TRACE_PROBE, "Unregistering video device in disconnect().\n");
! //	pwc_remove_sysfs_files(pdev->vdev);
  	video_unregister_device(pdev->vdev);
  
  	/* Free memory (don't set pdev to 0 just yet) */
+ 	kfree(pdev->vdev);
  	kfree(pdev);
  
  	/* search device_hint[] table if we occupy a slot, by any chance */
  	for (hint = 0; hint < MAX_DEV_HINTS; hint++)
  		if (device_hint[hint].pdev == pdev)
***************
*** 1776,1801 ****
  static int fps = 0;
  static int fbufs = 0;
  static int mbufs = 0;
  static int compression = -1;
  static int leds[2] = { -1, -1 };
  static int leds_nargs;
  static char *dev_hint[MAX_DEV_HINTS];
  static int dev_hint_nargs;
  
! module_param(size, charp, 0444);
! module_param(fps, int, 0444);
! module_param(fbufs, int, 0444);
! module_param(mbufs, int, 0444);
! module_param_named(trace, pwc_trace, int, 0644);
! module_param(power_save, int, 0444);
! module_param(compression, int, 0444);
! #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,10)
! module_param_array(leds, int, leds_nargs, 0444);
! module_param_array(dev_hint, charp, dev_hint_nargs, 0444);
! #else
! module_param_array(leds, int, &leds_nargs, 0444);
! module_param_array(dev_hint, charp, &dev_hint_nargs, 0444);
! #endif
  
  MODULE_PARM_DESC(size, "Initial image size. One of sqcif, qsif, qcif, sif, cif, vga");
  MODULE_PARM_DESC(fps, "Initial frames per second. Varies with model, useful range 5-30");
--- 2108,2138 ----
  static int fps = 0;
  static int fbufs = 0;
  static int mbufs = 0;
+ static int trace = -1;
  static int compression = -1;
  static int leds[2] = { -1, -1 };
  static int leds_nargs;
  static char *dev_hint[MAX_DEV_HINTS];
  static int dev_hint_nargs;
  
! MODULE_PARM(size, "s");
! //module_param(size, charp, 0444);
! MODULE_PARM(fps, "i");
! //module_param(fps, int, 0444);
! MODULE_PARM(fbufs, "i");
! //module_param(fbufs, int, 0444);
! MODULE_PARM(mbufs, "i");
! //module_param(mbufs, int, 0444);
! MODULE_PARM(trace, "i");
! //module_param_named(trace, pwc_trace, int, 0644);
! MODULE_PARM(power_save, "i");
! //module_param(power_save, int, 0444);
! MODULE_PARM(compression, "i");
! //module_param(compression, int, 0444);
! MODULE_PARM(leds, "2i");
! //module_param_array(leds, int, leds_nargs, 0444);
! MODULE_PARM(dev_hint, "0-20s");
! //module_param_array(dev_hint, charp, dev_hint_nargs, 0444);
  
  MODULE_PARM_DESC(size, "Initial image size. One of sqcif, qsif, qcif, sif, cif, vga");
  MODULE_PARM_DESC(fps, "Initial frames per second. Varies with model, useful range 5-30");
***************
*** 1808,1817 ****
  MODULE_PARM_DESC(dev_hint, "Device node hints");
  
  MODULE_DESCRIPTION("Philips & OEM USB webcam driver");
! MODULE_AUTHOR("Luc Saillard <luc@saillard.org>");
  MODULE_LICENSE("GPL");
- MODULE_ALIAS("pwcx");
- MODULE_VERSION( PWC_VERSION );
  
  static int __init usb_pwc_init(void)
  {
--- 2145,2152 ----
  MODULE_PARM_DESC(dev_hint, "Device node hints");
  
  MODULE_DESCRIPTION("Philips & OEM USB webcam driver");
! MODULE_AUTHOR("Nemosoft Unv. <webcam@smcc.demon.nl>");
  MODULE_LICENSE("GPL");
  
  static int __init usb_pwc_init(void)
  {
***************
*** 1962,1965 ****
  module_init(usb_pwc_init);
  module_exit(usb_pwc_exit);
  
- /* vim: set cino= formatoptions=croql cindent shiftwidth=8 tabstop=8: */
--- 2297,2299 ----
diff -c old/pwc.h new/pwc.h
*** old/pwc.h	Sun Apr 10 15:30:10 2005
--- new/pwc.h	Sun Apr 24 09:52:32 2005
***************
*** 32,38 ****
  #include <linux/usb.h>
  #include <linux/spinlock.h>
  #include <linux/videodev.h>
- #include <linux/videodev2.h>
  #include <linux/wait.h>
  #include <linux/smp_lock.h>
  #include <asm/semaphore.h>
--- 32,37 ----
***************
*** 41,46 ****
--- 40,48 ----
  #include "pwc-uncompress.h"
  #include "pwc-ioctl.h"
  
+ #define PWC_MAGIC 0x89DC10ABUL
+ #undef PWC_MAGIC
+ 
  /* Turn some debugging options on/off */
  #define PWC_DEBUG 0
  
