fedora core 6 1.2949 + vserver 2.2.0
[linux-2.6.git] / drivers / usb / image / mdc800.c
index b05c168..63a84bb 100644 (file)
@@ -23,7 +23,7 @@
  *
  *
  * The driver brings the USB functions of the MDC800 to Linux.
- * To use the Camera you must support the USB Protocoll of the camera
+ * To use the Camera you must support the USB Protocol of the camera
  * to the Kernel Node.
  * The Driver uses a misc device Node. Create it with :
  * mknod /dev/mustek c 180 32
@@ -95,6 +95,8 @@
 #include <linux/slab.h>
 #include <linux/module.h>
 #include <linux/smp_lock.h>
+#include <linux/wait.h>
+#include <linux/mutex.h>
 
 #include <linux/usb.h>
 #include <linux/fs.h>
@@ -168,7 +170,7 @@ struct mdc800_data
        int                     out_count;      // Bytes in the buffer
 
        int                     open;           // Camera device open ?
-       struct semaphore        io_lock;        // IO -lock
+       struct mutex            io_lock;        // IO -lock
 
        char                    in [8];         // Command Input Buffer
        int                     in_count;
@@ -182,15 +184,50 @@ struct mdc800_data
 /* Specification of the Endpoints */
 static struct usb_endpoint_descriptor mdc800_ed [4] =
 {
-       { 0,0, 0x01, 0x02,  8, 0,0,0 },
-       { 0,0, 0x82, 0x03,  8, 0,0,0 },
-       { 0,0, 0x03, 0x02, 64, 0,0,0 },
-       { 0,0, 0x84, 0x02, 64, 0,0,0 }
+       { 
+               .bLength =              0,
+               .bDescriptorType =      0,
+               .bEndpointAddress =     0x01,
+               .bmAttributes =         0x02,
+               .wMaxPacketSize =       __constant_cpu_to_le16(8),
+               .bInterval =            0,
+               .bRefresh =             0,
+               .bSynchAddress =        0,
+       },
+       {
+               .bLength =              0,
+               .bDescriptorType =      0,
+               .bEndpointAddress =     0x82,
+               .bmAttributes =         0x03,
+               .wMaxPacketSize =       __constant_cpu_to_le16(8),
+               .bInterval =            0,
+               .bRefresh =             0,
+               .bSynchAddress =        0,
+       },
+       {
+               .bLength =              0,
+               .bDescriptorType =      0,
+               .bEndpointAddress =     0x03,
+               .bmAttributes =         0x02,
+               .wMaxPacketSize =       __constant_cpu_to_le16(64),
+               .bInterval =            0,
+               .bRefresh =             0,
+               .bSynchAddress =        0,
+       },
+       {
+               .bLength =              0,
+               .bDescriptorType =      0,
+               .bEndpointAddress =     0x84,
+               .bmAttributes =         0x02,
+               .wMaxPacketSize =       __constant_cpu_to_le16(64),
+               .bInterval =            0,
+               .bRefresh =             0,
+               .bSynchAddress =        0,
+       },
 };
 
-
 /* The Variable used by the driver */
-static struct mdc800_data* mdc800=0;
+static struct mdc800_data* mdc800;
 
 
 /***************************************************************************
@@ -243,7 +280,7 @@ static int mdc800_isReady (char *ch)
 /*
  * USB IRQ Handler for InputLine
  */
-static void mdc800_usb_irq (struct urb *urb, struct pt_regs *res)
+static void mdc800_usb_irq (struct urb *urb)
 {
        int data_received=0, wake_up;
        unsigned char* b=urb->transfer_buffer;
@@ -295,7 +332,7 @@ static void mdc800_usb_irq (struct urb *urb, struct pt_regs *res)
        {
                mdc800->camera_request_ready=0;
                mdc800->irq_woken=1;
-               wake_up_interruptible (&mdc800->irq_wait);
+               wake_up (&mdc800->irq_wait);
        }
 }
 
@@ -311,21 +348,9 @@ static void mdc800_usb_irq (struct urb *urb, struct pt_regs *res)
  */
 static int mdc800_usb_waitForIRQ (int mode, int msec)
 {
-        DECLARE_WAITQUEUE(wait, current);
-       long timeout;
-
        mdc800->camera_request_ready=1+mode;
 
-       add_wait_queue(&mdc800->irq_wait, &wait);
-       set_current_state(TASK_INTERRUPTIBLE);
-       timeout = msec*HZ/1000;
-       while (!mdc800->irq_woken && timeout)
-       {
-               set_current_state(TASK_UNINTERRUPTIBLE);
-               timeout = schedule_timeout (timeout);
-       }
-        remove_wait_queue(&mdc800->irq_wait, &wait);
-       set_current_state(TASK_RUNNING);
+       wait_event_timeout(mdc800->irq_wait, mdc800->irq_woken, msec*HZ/1000);
        mdc800->irq_woken = 0;
 
        if (mdc800->camera_request_ready>0)
@@ -349,7 +374,7 @@ static int mdc800_usb_waitForIRQ (int mode, int msec)
 /*
  * The write_urb callback function
  */
-static void mdc800_usb_write_notify (struct urb *urb, struct pt_regs *res)
+static void mdc800_usb_write_notify (struct urb *urb)
 {
        struct mdc800_data* mdc800=urb->context;
 
@@ -362,14 +387,14 @@ static void mdc800_usb_write_notify (struct urb *urb, struct pt_regs *res)
                mdc800->state=READY;
        }
        mdc800->written = 1;
-       wake_up_interruptible (&mdc800->write_wait);
+       wake_up (&mdc800->write_wait);
 }
 
 
 /*
  * The download_urb callback function
  */
-static void mdc800_usb_download_notify (struct urb *urb, struct pt_regs *res)
+static void mdc800_usb_download_notify (struct urb *urb)
 {
        struct mdc800_data* mdc800=urb->context;
 
@@ -390,7 +415,7 @@ static void mdc800_usb_download_notify (struct urb *urb, struct pt_regs *res)
                err ("request bytes fails (status:%i)", urb->status);
        }
        mdc800->downloaded = 1;
-       wake_up_interruptible (&mdc800->download_wait);
+       wake_up (&mdc800->download_wait);
 }
 
 
@@ -399,11 +424,10 @@ static void mdc800_usb_download_notify (struct urb *urb, struct pt_regs *res)
  ***************************************************************************/
 
 static struct usb_driver mdc800_usb_driver;
-static struct file_operations mdc800_device_ops;
+static const struct file_operations mdc800_device_ops;
 static struct usb_class_driver mdc800_class = {
-       .name =         "usb/mdc800%d",
+       .name =         "mdc800%d",
        .fops =         &mdc800_device_ops,
-       .mode =         S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP,
        .minor_base =   MDC800_DEVICE_MINOR_BASE,
 };
 
@@ -423,7 +447,7 @@ static int mdc800_usb_probe (struct usb_interface *intf,
        dbg ("(mdc800_usb_probe) called.");
 
 
-       if (mdc800->dev != 0)
+       if (mdc800->dev != NULL)
        {
                warn ("only one Mustek MDC800 is supported.");
                return -ENODEV;
@@ -474,7 +498,7 @@ static int mdc800_usb_probe (struct usb_interface *intf,
 
        info ("Found Mustek MDC800 on USB.");
 
-       down (&mdc800->io_lock);
+       mutex_lock(&mdc800->io_lock);
 
        retval = usb_register_dev(intf, &mdc800_class);
        if (retval) {
@@ -519,7 +543,7 @@ static int mdc800_usb_probe (struct usb_interface *intf,
 
        mdc800->state=READY;
 
-       up (&mdc800->io_lock);
+       mutex_unlock(&mdc800->io_lock);
        
        usb_set_intfdata(intf, mdc800);
        return 0;
@@ -543,11 +567,11 @@ static void mdc800_usb_disconnect (struct usb_interface *intf)
 
                mdc800->state=NOT_CONNECTED;
 
-               usb_unlink_urb (mdc800->irq_urb);
-               usb_unlink_urb (mdc800->write_urb);
-               usb_unlink_urb (mdc800->download_urb);
+               usb_kill_urb(mdc800->irq_urb);
+               usb_kill_urb(mdc800->write_urb);
+               usb_kill_urb(mdc800->download_urb);
 
-               mdc800->dev=0;
+               mdc800->dev = NULL;
                usb_set_intfdata(intf, NULL);
        }
        info ("Mustek MDC800 disconnected from USB.");
@@ -597,7 +621,7 @@ static int mdc800_device_open (struct inode* inode, struct file *file)
        int retval=0;
        int errn=0;
 
-       down (&mdc800->io_lock);
+       mutex_lock(&mdc800->io_lock);
        
        if (mdc800->state == NOT_CONNECTED)
        {
@@ -633,7 +657,7 @@ static int mdc800_device_open (struct inode* inode, struct file *file)
        dbg ("Mustek MDC800 device opened.");
 
 error_out:
-       up (&mdc800->io_lock);
+       mutex_unlock(&mdc800->io_lock);
        return errn;
 }
 
@@ -646,12 +670,12 @@ static int mdc800_device_release (struct inode* inode, struct file *file)
        int retval=0;
        dbg ("Mustek MDC800 device closed.");
 
-       down (&mdc800->io_lock);
+       mutex_lock(&mdc800->io_lock);
        if (mdc800->open && (mdc800->state != NOT_CONNECTED))
        {
-               usb_unlink_urb (mdc800->irq_urb);
-               usb_unlink_urb (mdc800->write_urb);
-               usb_unlink_urb (mdc800->download_urb);
+               usb_kill_urb(mdc800->irq_urb);
+               usb_kill_urb(mdc800->write_urb);
+               usb_kill_urb(mdc800->download_urb);
                mdc800->open=0;
        }
        else
@@ -659,7 +683,7 @@ static int mdc800_device_release (struct inode* inode, struct file *file)
                retval=-EIO;
        }
 
-       up(&mdc800->io_lock);
+       mutex_unlock(&mdc800->io_lock);
        return retval;
 }
 
@@ -667,28 +691,26 @@ static int mdc800_device_release (struct inode* inode, struct file *file)
 /*
  * The Device read callback Function
  */
-static ssize_t mdc800_device_read (struct file *file, char *buf, size_t len, loff_t *pos)
+static ssize_t mdc800_device_read (struct file *file, char __user *buf, size_t len, loff_t *pos)
 {
        size_t left=len, sts=len; /* single transfer size */
-       char* ptr=buf;
-       long timeout;
-       DECLARE_WAITQUEUE(wait, current);
+       char __user *ptr = buf;
 
-       down (&mdc800->io_lock);
+       mutex_lock(&mdc800->io_lock);
        if (mdc800->state == NOT_CONNECTED)
        {
-               up (&mdc800->io_lock);
+               mutex_unlock(&mdc800->io_lock);
                return -EBUSY;
        }
        if (mdc800->state == WORKING)
        {
                warn ("Illegal State \"working\" reached during read ?!");
-               up (&mdc800->io_lock);
+               mutex_unlock(&mdc800->io_lock);
                return -EBUSY;
        }
        if (!mdc800->open)
        {
-               up (&mdc800->io_lock);
+               mutex_unlock(&mdc800->io_lock);
                return -EBUSY;
        }
 
@@ -696,7 +718,7 @@ static ssize_t mdc800_device_read (struct file *file, char *buf, size_t len, lof
        {
                if (signal_pending (current)) 
                {
-                       up (&mdc800->io_lock);
+                       mutex_unlock(&mdc800->io_lock);
                        return -EINTR;
                }
 
@@ -715,30 +737,23 @@ static ssize_t mdc800_device_read (struct file *file, char *buf, size_t len, lof
                                if (usb_submit_urb (mdc800->download_urb, GFP_KERNEL))
                                {
                                        err ("Can't submit download urb (status=%i)",mdc800->download_urb->status);
-                                       up (&mdc800->io_lock);
+                                       mutex_unlock(&mdc800->io_lock);
                                        return len-left;
                                }
-                               add_wait_queue(&mdc800->download_wait, &wait);
-                               timeout = TO_DOWNLOAD_GET_READY*HZ/1000;
-                               while (!mdc800->downloaded && timeout)
-                               {
-                                       set_current_state(TASK_UNINTERRUPTIBLE);
-                                       timeout = schedule_timeout (timeout);
-                               }
-                               set_current_state(TASK_RUNNING);
-                               remove_wait_queue(&mdc800->download_wait, &wait);
+                               wait_event_timeout(mdc800->download_wait, mdc800->downloaded,
+                                                                               TO_DOWNLOAD_GET_READY*HZ/1000);
                                mdc800->downloaded = 0;
                                if (mdc800->download_urb->status != 0)
                                {
                                        err ("request download-bytes fails (status=%i)",mdc800->download_urb->status);
-                                       up (&mdc800->io_lock);
+                                       mutex_unlock(&mdc800->io_lock);
                                        return len-left;
                                }
                        }
                        else
                        {
                                /* No more bytes -> that's an error*/
-                               up (&mdc800->io_lock);
+                               mutex_unlock(&mdc800->io_lock);
                                return -EIO;
                        }
                }
@@ -747,7 +762,7 @@ static ssize_t mdc800_device_read (struct file *file, char *buf, size_t len, lof
                        /* Copy Bytes */
                        if (copy_to_user(ptr, &mdc800->out [mdc800->out_ptr],
                                                sts)) {
-                               up(&mdc800->io_lock);
+                               mutex_unlock(&mdc800->io_lock);
                                return -EFAULT;
                        }
                        ptr+=sts;
@@ -756,7 +771,7 @@ static ssize_t mdc800_device_read (struct file *file, char *buf, size_t len, lof
                }
        }
 
-       up (&mdc800->io_lock);
+       mutex_unlock(&mdc800->io_lock);
        return len-left;
 }
 
@@ -767,20 +782,19 @@ static ssize_t mdc800_device_read (struct file *file, char *buf, size_t len, lof
  * After this the driver initiates the request for the answer or
  * just waits until the camera becomes ready.
  */
-static ssize_t mdc800_device_write (struct file *file, const char *buf, size_t len, loff_t *pos)
+static ssize_t mdc800_device_write (struct file *file, const char __user *buf, size_t len, loff_t *pos)
 {
        size_t i=0;
-       DECLARE_WAITQUEUE(wait, current);
 
-       down (&mdc800->io_lock);
+       mutex_lock(&mdc800->io_lock);
        if (mdc800->state != READY)
        {
-               up (&mdc800->io_lock);
+               mutex_unlock(&mdc800->io_lock);
                return -EBUSY;
        }
        if (!mdc800->open )
        {
-               up (&mdc800->io_lock);
+               mutex_unlock(&mdc800->io_lock);
                return -EBUSY;
        }
 
@@ -789,13 +803,13 @@ static ssize_t mdc800_device_write (struct file *file, const char *buf, size_t l
                unsigned char c;
                if (signal_pending (current)) 
                {
-                       up (&mdc800->io_lock);
+                       mutex_unlock(&mdc800->io_lock);
                        return -EINTR;
                }
                
                if(get_user(c, buf+i))
                {
-                       up(&mdc800->io_lock);
+                       mutex_unlock(&mdc800->io_lock);
                        return -EFAULT;
                }
 
@@ -816,7 +830,7 @@ static ssize_t mdc800_device_write (struct file *file, const char *buf, size_t l
                }
                else
                {
-                       up (&mdc800->io_lock);
+                       mutex_unlock(&mdc800->io_lock);
                        return -EIO;
                }
 
@@ -824,12 +838,11 @@ static ssize_t mdc800_device_write (struct file *file, const char *buf, size_t l
                if (mdc800->in_count == 8)
                {
                        int answersize;
-                       long timeout;
 
                        if (mdc800_usb_waitForIRQ (0,TO_GET_READY))
                        {
                                err ("Camera didn't get ready.\n");
-                               up (&mdc800->io_lock);
+                               mutex_unlock(&mdc800->io_lock);
                                return -EIO;
                        }
 
@@ -841,23 +854,15 @@ static ssize_t mdc800_device_write (struct file *file, const char *buf, size_t l
                        if (usb_submit_urb (mdc800->write_urb, GFP_KERNEL))
                        {
                                err ("submitting write urb fails (status=%i)", mdc800->write_urb->status);
-                               up (&mdc800->io_lock);
+                               mutex_unlock(&mdc800->io_lock);
                                return -EIO;
                        }
-                       add_wait_queue(&mdc800->write_wait, &wait);
-                       timeout = TO_WRITE_GET_READY*HZ/1000;
-                       while (!mdc800->written && timeout)
-                       {
-                               set_current_state(TASK_UNINTERRUPTIBLE);
-                               timeout = schedule_timeout (timeout);
-                       }
-                        set_current_state(TASK_RUNNING);
-                       remove_wait_queue(&mdc800->write_wait, &wait);
+                       wait_event_timeout(mdc800->write_wait, mdc800->written, TO_WRITE_GET_READY*HZ/1000);
                        mdc800->written = 0;
                        if (mdc800->state == WORKING)
                        {
-                               usb_unlink_urb (mdc800->write_urb);
-                               up (&mdc800->io_lock);
+                               usb_kill_urb(mdc800->write_urb);
+                               mutex_unlock(&mdc800->io_lock);
                                return -EIO;
                        }
 
@@ -869,7 +874,7 @@ static ssize_t mdc800_device_write (struct file *file, const char *buf, size_t l
                                        {
                                                err ("call 0x07 before 0x05,0x3e");
                                                mdc800->state=READY;
-                                               up (&mdc800->io_lock);
+                                               mutex_unlock(&mdc800->io_lock);
                                                return -EIO;
                                        }
                                        mdc800->pic_len=-1;
@@ -888,7 +893,7 @@ static ssize_t mdc800_device_write (struct file *file, const char *buf, size_t l
                                                if (mdc800_usb_waitForIRQ (1,TO_READ_FROM_IRQ))
                                                {
                                                        err ("requesting answer from irq fails");
-                                                       up (&mdc800->io_lock);
+                                                       mutex_unlock(&mdc800->io_lock);
                                                        return -EIO;
                                                }
 
@@ -916,7 +921,7 @@ static ssize_t mdc800_device_write (struct file *file, const char *buf, size_t l
                                                if (mdc800_usb_waitForIRQ (0,TO_DEFAULT_COMMAND))
                                                {
                                                        err ("Command Timeout.");
-                                                       up (&mdc800->io_lock);
+                                                       mutex_unlock(&mdc800->io_lock);
                                                        return -EIO;
                                                }
                                        }
@@ -926,7 +931,7 @@ static ssize_t mdc800_device_write (struct file *file, const char *buf, size_t l
                }
                i++;
        }
-       up (&mdc800->io_lock);
+       mutex_unlock(&mdc800->io_lock);
        return i;
 }
 
@@ -936,7 +941,7 @@ static ssize_t mdc800_device_write (struct file *file, const char *buf, size_t l
 ****************************************************************************/
 
 /* File Operations of this drivers */
-static struct file_operations mdc800_device_ops =
+static const struct file_operations mdc800_device_ops =
 {
        .owner =        THIS_MODULE,
        .read =         mdc800_device_read,
@@ -958,7 +963,6 @@ MODULE_DEVICE_TABLE (usb, mdc800_table);
  */
 static struct usb_driver mdc800_usb_driver =
 {
-       .owner =        THIS_MODULE,
        .name =         "mdc800",
        .probe =        mdc800_usb_probe,
        .disconnect =   mdc800_usb_disconnect,
@@ -971,21 +975,17 @@ static struct usb_driver mdc800_usb_driver =
        Init and Cleanup this driver (Main Functions)
 *************************************************************************/
 
-#define try(A)           if ((A) == 0) goto cleanup_on_fail;
-#define try_free_mem(A)  if (A != 0) { kfree (A); A=0; }
-#define try_free_urb(A)  if (A != 0) { usb_free_urb (A); A=0; }
-
 static int __init usb_mdc800_init (void)
 {
        int retval = -ENODEV;
        /* Allocate Memory */
-       try (mdc800=kmalloc (sizeof (struct mdc800_data), GFP_KERNEL));
+       mdc800=kzalloc (sizeof (struct mdc800_data), GFP_KERNEL);
+       if (!mdc800)
+               goto cleanup_on_fail;
 
-       memset(mdc800, 0, sizeof(struct mdc800_data));
-       mdc800->dev=0;
-       mdc800->open=0;
+       mdc800->dev = NULL;
        mdc800->state=NOT_CONNECTED;
-       init_MUTEX (&mdc800->io_lock);
+       mutex_init (&mdc800->io_lock);
 
        init_waitqueue_head (&mdc800->irq_wait);
        init_waitqueue_head (&mdc800->write_wait);
@@ -995,13 +995,25 @@ static int __init usb_mdc800_init (void)
        mdc800->downloaded = 0;
        mdc800->written = 0;
 
-       try (mdc800->irq_urb_buffer=kmalloc (8, GFP_KERNEL));
-       try (mdc800->write_urb_buffer=kmalloc (8, GFP_KERNEL));
-       try (mdc800->download_urb_buffer=kmalloc (64, GFP_KERNEL));
+       mdc800->irq_urb_buffer=kmalloc (8, GFP_KERNEL);
+       if (!mdc800->irq_urb_buffer)
+               goto cleanup_on_fail;
+       mdc800->write_urb_buffer=kmalloc (8, GFP_KERNEL);
+       if (!mdc800->write_urb_buffer)
+               goto cleanup_on_fail;
+       mdc800->download_urb_buffer=kmalloc (64, GFP_KERNEL);
+       if (!mdc800->download_urb_buffer)
+               goto cleanup_on_fail;
 
-       try (mdc800->irq_urb=usb_alloc_urb (0, GFP_KERNEL));
-       try (mdc800->download_urb=usb_alloc_urb (0, GFP_KERNEL));
-       try (mdc800->write_urb=usb_alloc_urb (0, GFP_KERNEL));
+       mdc800->irq_urb=usb_alloc_urb (0, GFP_KERNEL);
+       if (!mdc800->irq_urb)
+               goto cleanup_on_fail;
+       mdc800->download_urb=usb_alloc_urb (0, GFP_KERNEL);
+       if (!mdc800->download_urb)
+               goto cleanup_on_fail;
+       mdc800->write_urb=usb_alloc_urb (0, GFP_KERNEL);
+       if (!mdc800->write_urb)
+               goto cleanup_on_fail;
 
        /* Register the driver */
        retval = usb_register(&mdc800_usb_driver);
@@ -1016,21 +1028,21 @@ static int __init usb_mdc800_init (void)
 
 cleanup_on_fail:
 
-       if (mdc800 != 0)
+       if (mdc800 != NULL)
        {
                err ("can't alloc memory!");
 
-               try_free_mem (mdc800->download_urb_buffer);
-               try_free_mem (mdc800->write_urb_buffer);
-               try_free_mem (mdc800->irq_urb_buffer);
+               kfree(mdc800->download_urb_buffer);
+               kfree(mdc800->write_urb_buffer);
+               kfree(mdc800->irq_urb_buffer);
 
-               try_free_urb (mdc800->write_urb);
-               try_free_urb (mdc800->download_urb);
-               try_free_urb (mdc800->irq_urb);
+               usb_free_urb(mdc800->write_urb);
+               usb_free_urb(mdc800->download_urb);
+               usb_free_urb(mdc800->irq_urb);
 
                kfree (mdc800);
        }
-       mdc800=0;
+       mdc800 = NULL;
        return retval;
 }
 
@@ -1048,7 +1060,7 @@ static void __exit usb_mdc800_cleanup (void)
        kfree (mdc800->download_urb_buffer);
 
        kfree (mdc800);
-       mdc800=0;
+       mdc800 = NULL;
 }
 
 module_init (usb_mdc800_init);