(patch 1 of 2)

Hi,

Here's a patch for the usb scanner driver against 2.2.20-pre2 that
brings it up to the same logic level that is in 2.4.5.

thanks,

greg k-h
diff -Nru a/drivers/usb/scanner.c b/drivers/usb/scanner.c
--- a/drivers/usb/scanner.c     Wed Jun 13 21:02:21 2001
+++ b/drivers/usb/scanner.c     Wed Jun 13 21:02:21 2001
@@ -1,7 +1,7 @@
 /* -*- linux-c -*- */
 
 /* 
- * Driver for USB Scanners (linux-2.4.0test1-ac7)
+ * Driver for USB Scanners (linux-2.4.0)
  *
  * Copyright (C) 1999, 2000 David E. Nelson
  *
@@ -199,6 +199,34 @@
  *    - Fixed HP S20 ID's...again..sigh.  Thanks to Ruud
  *      Linders <[EMAIL PROTECTED]>.
  *
+ * 0.4.4
+ *    - Added addtional Mustek ID's (BearPaw 1200, 600 CU, 1200 USB,
+ *      and 1200 UB.  Thanks to Henning Meier-Geinitz <[EMAIL PROTECTED]>.
+ *    - Added the Vuego Scan Brisa 340U ID's.  Apparently this scanner is
+ *      marketed by Acer Peripherals as a cheap 300 dpi model. Thanks to
+ *      David Gundersen <[EMAIL PROTECTED]>.
+ *    - Added the Epson Expression1600 ID's. Thanks to Karl Heinz
+ *      Kremer <[EMAIL PROTECTED]>.
+ *
+ * 0.4.5  2/28/2001
+ *    - Added Mustek ID's (BearPaw 2400, 1200 CU Plus, BearPaw 1200F).
+ *      Thanks to Henning Meier-Geinitz <[EMAIL PROTECTED]>.
+ *    - Added read_timeout module parameter to override RD_NAK_TIMEOUT
+ *      when read()'ing from devices.
+ *    - Stalled pipes are now checked and cleared with
+ *      usb_clear_halt() for the read_scanner() function. This should
+ *      address the "funky result: -32" error messages.
+ *    - Removed Microtek scanner ID's.  Microtek scanners are now
+ *      supported via the drivers/usb/microtek.c driver.
+ *    - Added scanner specific read timeout's.
+ *    - Return status errors are NEGATIVE!!!  This should address the
+ *      "funky result: -110" error messages.
+ *    - Replaced USB_ST_TIMEOUT with ETIMEDOUT.
+ *    - rd_nak was still defined in MODULE_PARM.  It's been updated with
+ *      read_timeout.  Thanks to Mark W. Webb <[EMAIL PROTECTED]> for
+ *      reporting this bug.
+ *    - Added Epson Perfection 1640SU and 1640SU Photo.  Thanks to
+ *      Jean-Luc <[EMAIL PROTECTED]>.
  *
  *  TODO
  *
@@ -236,6 +264,7 @@
  */ 
 #include "scanner.h"
 
+
 static void
 irq_scanner(struct urb *urb)
 {
@@ -266,13 +295,18 @@
 
        kdev_t scn_minor;
 
+       int err=0;
+
+       lock_kernel();
+
        scn_minor = USB_SCN_MINOR(inode);
 
        dbg("open_scanner: scn_minor:%d", scn_minor);
 
        if (!p_scn_table[scn_minor]) {
                err("open_scanner(%d): Unable to access minor data", scn_minor);
-               return -ENODEV;
+               err = -ENODEV;
+               goto out_error;
        }
 
        scn = p_scn_table[scn_minor];
@@ -281,17 +315,20 @@
 
        if (!dev) {
                err("open_scanner(%d): Scanner device not present", scn_minor);
-               return -ENODEV;
+               err = -ENODEV;
+               goto out_error;
        }
 
        if (!scn->present) {
                err("open_scanner(%d): Scanner is not present", scn_minor);
-               return -ENODEV;
+               err = -ENODEV;
+               goto out_error;
        }
 
        if (scn->isopen) {
                err("open_scanner(%d): Scanner device is already open", scn_minor);
-               return -EBUSY;
+               err = -EBUSY;
+               goto out_error;
        }
 
        init_waitqueue_head(&scn->rd_wait_q);
@@ -302,7 +339,11 @@
 
        MOD_INC_USE_COUNT;
 
-       return 0;
+out_error:
+
+       unlock_kernel();
+
+       return err;
 }
 
 static int
@@ -338,7 +379,7 @@
 {
        struct scn_usb_data *scn;
        struct usb_device *dev;
-       
+
        ssize_t bytes_written = 0; /* Overall count of bytes written */
        ssize_t ret = 0;
 
@@ -347,7 +388,7 @@
        int this_write;         /* Number of bytes to write */
        int partial;            /* Number of bytes successfully written */
        int result = 0;
-       
+
        char *obuf;
 
        scn = file->private_data;
@@ -360,6 +401,8 @@
 
        file->f_dentry->d_inode->i_atime = CURRENT_TIME;
 
+       down(&(scn->gen_lock));
+
        while (count > 0) {
 
                if (signal_pending(current)) {
@@ -368,7 +411,7 @@
                }
 
                this_write = (count >= OBUF_SIZE) ? OBUF_SIZE : count;
-               
+
                if (copy_from_user(scn->obuf, buffer, this_write)) {
                        ret = -EFAULT;
                        break;
@@ -377,15 +420,15 @@
                result = usb_bulk_msg(dev,usb_sndbulkpipe(dev, scn->bulk_out_ep), 
obuf, this_write, &partial, 60*HZ);
                dbg("write stats(%d): result:%d this_write:%d partial:%d", scn_minor, 
result, this_write, partial);
 
-               if (result == USB_ST_TIMEOUT) { /* NAK -- shouldn't happen */
+               if (result == -ETIMEDOUT) {     /* NAK -- shouldn't happen */
                        warn("write_scanner: NAK received.");
-                       ret = -ETIME;
+                       ret = result;
                        break;
                } else if (result < 0) { /* We should not get any I/O errors */
                        warn("write_scanner(%d): funky result: %d. Please notify the 
maintainer.", scn_minor, result);
                        ret = -EIO;
                        break;
-               } 
+               }
 
 #ifdef WR_DATA_DUMP
                if (partial) {
@@ -412,6 +455,7 @@
                        break;
                }
        }
+       up(&(scn->gen_lock));
        mdelay(5);              /* This seems to help with SANE queries */
        return ret ? ret : bytes_written;
 }
@@ -450,6 +494,7 @@
                                                             atime of
                                                             the device
                                                             node */
+       down(&(scn->gen_lock));
 
        while (count > 0) {
                if (signal_pending(current)) {
@@ -458,11 +503,11 @@
                }
 
                this_read = (count >= IBUF_SIZE) ? IBUF_SIZE : count;
-               
-               result = usb_bulk_msg(dev, usb_rcvbulkpipe(dev, scn->bulk_in_ep), 
ibuf, this_read, &partial, RD_NAK_TIMEOUT);
+
+               result = usb_bulk_msg(dev, usb_rcvbulkpipe(dev, scn->bulk_in_ep), 
+ibuf, this_read, &partial, scn->rd_nak_timeout);
                dbg("read stats(%d): result:%d this_read:%d partial:%d count:%d", 
scn_minor, result, this_read, partial, count);
 
-/* 
+/*
  * Scanners are sometimes inheriently slow since they are mechanical
  * in nature.  USB bulk reads tend to timeout while the scanner is
  * positioning, resetting, warming up the lamp, etc if the timeout is
@@ -473,26 +518,38 @@
  * that something had hung or crashed when in fact the USB read was
  * just waiting on data.  So, the below code retains the same long
  * timeout period, but splits it up into smaller parts so that
- * Ctrl-C's are acted upon in a reasonable amount of time. 
+ * Ctrl-C's are acted upon in a reasonable amount of time.
  */
 
-               if (result == USB_ST_TIMEOUT && !partial) { /* Timeout
-                                                               and no
-                                                               data */
-                       if (--rd_expire <= 0) {
-                               warn("read_scanner(%d): excessive NAK's received", 
scn_minor);
-                               ret = -ETIME;
-                               break;
-                       } else {
-                               interruptible_sleep_on_timeout(&scn->rd_wait_q, 
RD_NAK_TIMEOUT);
-                               continue;
+               if (result == -ETIMEDOUT) { /* NAK */
+                       if (!partial) { /* No data */
+                               if (--rd_expire <= 0) { /* Give it up */
+                                       warn("read_scanner(%d): excessive NAK's 
+received", scn_minor);
+                                       ret = result;
+                                       break;
+                               } else { /* Keep trying to read data */
+                                       
+interruptible_sleep_on_timeout(&scn->rd_wait_q, scn->rd_nak_timeout);
+                                       continue;
+                               }
+                       } else { /* Timeout w/ some data */
+                               goto data_recvd;
                        }
+               }
+               
+               if (result == -EPIPE) { /* No hope */
+                       if(usb_clear_halt(dev, scn->bulk_in_ep)) {
+                               err("read_scanner(%d): Failure to clear endpoint halt 
+condition (%Zd).", scn_minor, ret);
+                       }
+                       ret = result;
+                       break;
                } else if ((result < 0) && (result != USB_ST_DATAUNDERRUN)) {
                        warn("read_scanner(%d): funky result:%d. Please notify the 
maintainer.", scn_minor, (int)result);
                        ret = -EIO;
                        break;
                }
 
+       data_recvd:
+
 #ifdef RD_DATA_DUMP
                if (partial) {
                        unsigned char cnt, cnt_max;
@@ -518,7 +575,8 @@
                        break;
                }
        }
-       
+       up(&(scn->gen_lock));
+
        return ret ? ret : bytes_read;
 }
 
@@ -528,7 +586,7 @@
        struct scn_usb_data *scn;
        struct usb_interface_descriptor *interface;
        struct usb_endpoint_descriptor *endpoint;
-       
+
        int ep_cnt;
        int ix;
 
@@ -550,7 +608,7 @@
  * 3. Determine/Assign Intr Endpoint
  */
 
-/* 
+/*
  * There doesn't seem to be an imaging class defined in the USB
  * Spec. (yet).  If there is, HP isn't following it and it doesn't
  * look like anybody else is either.  Therefore, we have to test the
@@ -577,7 +635,7 @@
            dev->descriptor.idProduct == product) { /* User specified */
                valid_device = 1;
        }
-       
+
         if (!valid_device)
                 return NULL;    /* We didn't find anything pleasing */
 
@@ -599,7 +657,7 @@
        interface = dev->config[0].interface[ifnum].altsetting;
        endpoint = interface[ifnum].endpoint;
 
-/* 
+/*
  * Start checking for two bulk endpoints OR two bulk endpoints *and* one
  * interrupt endpoint. If we have an interrupt endpoint go ahead and
  * setup the handler. FIXME: This is a future enhancement...
@@ -622,7 +680,7 @@
                        dbg("probe_scanner: bulk_in_ep:%d", have_bulk_in);
                        continue;
                }
-               
+
                if (!have_bulk_out && IS_EP_BULK_OUT(endpoint[ep_cnt])) {
                        ep_cnt++;
                        have_bulk_out = ep_cnt;
@@ -665,7 +723,7 @@
        }
 
 
-/* 
+/*
  * Determine a minor number and initialize the structure associated
  * with it.  The problem with this is that we are counting on the fact
  * that the user will sequentially add device nodes for the scanner
@@ -695,7 +753,7 @@
 /* Ok, if we detected an interrupt EP, setup a handler for it */
        if (have_intr) {
                dbg("probe_scanner(%d): Configuring IRQ handler for intr EP:%d", 
scn_minor, have_intr);
-               FILL_INT_URB(&scn->scn_irq, dev, 
+               FILL_INT_URB(&scn->scn_irq, dev,
                             usb_rcvintpipe(dev, have_intr),
                             &scn->button, 1, irq_scanner, scn,
                             // endpoint[(int)have_intr].bInterval);
@@ -724,6 +782,26 @@
                return NULL;
        }
        dbg("probe_scanner(%d): ibuf address:%p", scn_minor, scn->ibuf);
+       
+
+       switch (dev->descriptor.idVendor) { /* Scanner specific read timeout 
+parameters */
+       case 0x04b8:            /* Seiko/Epson */
+               scn->rd_nak_timeout = HZ * 40;
+               break;
+       case 0x055f:            /* Mustek */
+       case 0x0400:            /* Another Mustek */
+       case 0x0ff5:            /* And yet another Mustek */
+               scn->rd_nak_timeout = HZ * 1;
+       default:
+               scn->rd_nak_timeout = RD_NAK_TIMEOUT;
+       }
+
+
+       if (read_timeout > 0) { /* User specified read timeout overrides everything */
+               info("probe_scanner: User specified USB read timeout - %d", 
+read_timeout);
+               scn->rd_nak_timeout = read_timeout;
+       }
+
 
        scn->bulk_in_ep = have_bulk_in;
        scn->bulk_out_ep = have_bulk_out;
@@ -733,6 +811,8 @@
        scn->scn_minor = scn_minor;
        scn->isopen = 0;
 
+       init_MUTEX(&(scn->gen_lock));
+
        return p_scn_table[scn_minor] = scn;
 }
 
@@ -740,7 +820,7 @@
 disconnect_scanner(struct usb_device *dev, void *ptr)
 {
        struct scn_usb_data *scn = (struct scn_usb_data *) ptr;
-       
+
        if(scn->intr_ep) {
                dbg("disconnect_scanner(%d): Unlinking IRQ URB", scn->scn_minor);
                usb_unlink_urb(&scn->scn_irq);
@@ -762,11 +842,11 @@
              unsigned int cmd, unsigned long arg)
 {
        struct usb_device *dev;
-       
+
        int result;
 
        kdev_t scn_minor;
-       
+
        scn_minor = USB_SCN_MINOR(inode);
 
        if (!p_scn_table[scn_minor]) {
@@ -775,7 +855,7 @@
        }
 
        dev = p_scn_table[scn_minor]->scn_dev;
-       
+
        switch (cmd)
        {
        case PV8630_IOCTL_INREQUEST :
@@ -786,10 +866,10 @@
                        __u16 value;
                        __u16 index;
                } args;
-               
+
                if (copy_from_user(&args, (void *)arg, sizeof(args)))
                        return -EFAULT;
-               
+
                result = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
                                         args.request, USB_TYPE_VENDOR|
                                         USB_RECIP_DEVICE|USB_DIR_IN,
@@ -802,7 +882,7 @@
                        return -EFAULT;
 
                dbg("ioctl_scanner(%d): inreq: result:%d\n", scn_minor, result);
-               
+
                return result;
        }
        case PV8630_IOCTL_OUTREQUEST :
@@ -812,10 +892,10 @@
                        __u16 value;
                        __u16 index;
                } args;
-               
+
                if (copy_from_user(&args, (void *)arg, sizeof(args)))
                        return -EFAULT;
-               
+
                dbg("ioctl_scanner(%d): outreq: args.value:%x args.index:%x 
args.request:%x\n", scn_minor, args.value, args.index, args.request);
 
                result = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
@@ -825,7 +905,7 @@
                                         0, HZ*5);
 
                dbg("ioctl_scanner(%d): outreq: result:%d\n", scn_minor, result);
-               
+
                return result;
        }
        default:
@@ -848,12 +928,11 @@
 
 static struct
 usb_driver scanner_driver = {
-       "usbscanner",
-       probe_scanner,
-       disconnect_scanner,
-       { NULL, NULL },
-       &usb_scanner_fops,
-       SCN_BASE_MNR
+       name:           "usbscanner",
+       probe:          probe_scanner,
+       disconnect:     disconnect_scanner,
+       fops:           &usb_scanner_fops,
+       minor:          SCN_BASE_MNR,
 };
 
 void __exit
diff -Nru a/drivers/usb/scanner.h b/drivers/usb/scanner.h
--- a/drivers/usb/scanner.h     Wed Jun 13 21:02:21 2001
+++ b/drivers/usb/scanner.h     Wed Jun 13 21:02:21 2001
@@ -1,5 +1,5 @@
 /*
- * Driver for USB Scanners (linux-2.4.0test1-ac7)
+ * Driver for USB Scanners (linux-2.4.0)
  *
  * Copyright (C) 1999, 2000 David E. Nelson
  *
@@ -30,12 +30,13 @@
 #include <linux/delay.h>
 #include <linux/ioctl.h>
 #include <linux/sched.h>
+#include <linux/smp_lock.h>
 
 // #define DEBUG
 
 #include <linux/usb.h>
 
-static __s32 vendor=-1, product=-1;
+static __s32 vendor=-1, product=-1, read_timeout=0;
 
 MODULE_AUTHOR("David E. Nelson, [EMAIL PROTECTED], http://www.jump.net/~dnelson";);
 MODULE_DESCRIPTION("USB Scanner Driver");
@@ -46,6 +47,9 @@
 MODULE_PARM(product, "i");
 MODULE_PARM_DESC(product, "User specified USB idProduct");
 
+MODULE_PARM(read_timeout, "i");
+MODULE_PARM_DESC(read_timeout, "User specified read timeout in seconds");
+
 
 /* Enable to activate the ioctl interface.  This is mainly meant for */
 /* development purposes until an ioctl number is officially registered */
@@ -72,7 +76,7 @@
 #define OBUF_SIZE 4096
 
 /* read_scanner timeouts -- RD_NAK_TIMEOUT * RD_EXPIRE = Number of seconds */
-#define RD_NAK_TIMEOUT (10*HZ) /* Number of X seconds to wait */
+#define RD_NAK_TIMEOUT (10*HZ) /* Default number of X seconds to wait */
 #define RD_EXPIRE 12           /* Number of attempts to wait X seconds */
 
 
@@ -89,11 +93,13 @@
        unsigned int ifnum;     /* Interface number of the USB device */
        kdev_t scn_minor;       /* Scanner minor - used in disconnect() */
        unsigned char button;   /* Front panel buffer */
-        char isopen;           /* Not zero if the device is open */
+       char isopen;            /* Not zero if the device is open */
        char present;           /* Not zero if device is present */
        char *obuf, *ibuf;      /* transfer buffers */
        char bulk_in_ep, bulk_out_ep, intr_ep; /* Endpoint assignments */
        wait_queue_head_t rd_wait_q; /* read timeouts */
+       struct semaphore gen_lock; /* lock to prevent concurrent reads or writes */
+       unsigned int rd_nak_timeout; /* Seconds to wait before read() timeout. */
 };
 
 static struct scn_usb_data *p_scn_table[SCN_MAX_MNR] = { NULL, /* ... */};
@@ -106,8 +112,10 @@
        /* Acer */
                { 0x04a5, 0x2060 },     /* Prisa Acerscan 620U & 640U (!) */
                { 0x04a5, 0x2040 },     /* Prisa AcerScan 620U (!) */
+               { 0x04a5, 0x2022 },     /* Vuego Scan Brisa 340U */
        /* Agfa */
                { 0x06bd, 0x0001 },     /* SnapScan 1212U */
+               { 0x06bd, 0x0002 },     /* SnapScan 1236U */
                { 0x06bd, 0x2061 },     /* Another SnapScan 1212U (?) */
                { 0x06bd, 0x0100 },     /* SnapScan Touch */
        /* Colorado -- See Primax/Colorado below */
@@ -120,20 +128,28 @@
                { 0x03f0, 0x0105 },     /* 4200C */
                { 0x03f0, 0x0102 },     /* PhotoSmart S20 */
                { 0x03f0, 0x0401 },     /* 5200C */
+       //      { 0x03f0, 0x0701 },     /* 5300C - NOT SUPPORTED - see 
+http://www.neatech.nl/oss/HP5300C/ */
                { 0x03f0, 0x0201 },     /* 6200C */
                { 0x03f0, 0x0601 },     /* 6300C */
        /* iVina */
                { 0x0638, 0x0268 },     /* 1200U */
-       /* Microtek */
-               { 0x05da, 0x0099 },     /* ScanMaker X6 - X6U */
-               { 0x05da, 0x0094 },     /* Phantom 336CX - C3 */
-               { 0x05da, 0x00a0 },     /* Phantom 336CX - C3 #2 */
-               { 0x05da, 0x009a },     /* Phantom C6 */
-               { 0x05da, 0x00a3 },     /* ScanMaker V6USL */
-               { 0x05da, 0x80a3 },     /* ScanMaker V6USL #2 */
-               { 0x05da, 0x80ac },     /* ScanMaker V6UL - SpicyU */
+       /* Microtek No longer supported - Enable SCSI and USB Microtek in kernel 
+config */
+       //      { 0x05da, 0x0099 },     /* ScanMaker X6 - X6U */
+       //      { 0x05da, 0x0094 },     /* Phantom 336CX - C3 */
+       //      { 0x05da, 0x00a0 },     /* Phantom 336CX - C3 #2 */
+       //      { 0x05da, 0x009a },     /* Phantom C6 */
+       //      { 0x05da, 0x00a3 },     /* ScanMaker V6USL */
+       //      { 0x05da, 0x80a3 },     /* ScanMaker V6USL #2 */
+       //      { 0x05da, 0x80ac },     /* ScanMaker V6UL - SpicyU */
        /* Mustek */
                { 0x055f, 0x0001 },     /* 1200 CU */
+               { 0x0400, 0x1000 },     /* BearPaw 1200 */
+               { 0x055f, 0x0002 },     /* 600 CU */
+               { 0x055f, 0x0003 },     /* 1200 USB */
+               { 0x055f, 0x0006 },     /* 1200 UB */
+               { 0x0400, 0x1001 },     /* BearPaw 2400 */
+               { 0x055f, 0x0008 },     /* 1200 CU Plus */
+               { 0x0ff5, 0x0010 },     /* BearPaw 1200F */
        /* Primax/Colorado */
                { 0x0461, 0x0300 },     /* G2-300 #1 */
                { 0x0461, 0x0380 },     /* G2-600 #1 */
@@ -151,7 +167,11 @@
                { 0x04b8, 0x0101 },     /* Perfection 636U and 636Photo */
                { 0x04b8, 0x0103 },     /* Perfection 610 */
                { 0x04b8, 0x0104 },     /* Perfection 1200U and 1200Photo */
+               { 0x04b8, 0x0106 },     /* Stylus Scan 2500 */
+               { 0x04b8, 0x0107 },     /* Expression 1600 */
+               { 0x04b8, 0x010a },     /* Perfection 1640SU and 1640SU Photo */
                { 0x04b8, 0x010b },     /* Perfection 1240U and 1240Photo */
+               { 0x04b8, 0x010c },     /* Perfection 640U */
        /* Umax */
                { 0x1606, 0x0010 },     /* Astra 1220U */
                { 0x1606, 0x0002 },     /* Astra 1236U */
@@ -161,6 +181,10 @@
                { 0x04a7, 0x0221 },     /* OneTouch 5300 */
                { 0x04a7, 0x0221 },     /* OneTouch 7600 duplicate ID (!) */
                { 0x04a7, 0x0231 },     /* 6100 */
+               { 0x04a7, 0x0211 },     /* OneTouch 7600 USB */
+               { 0x04a7, 0x0311 },     /* 6200 EPP/USB */
+               { 0x04a7, 0x0321 },     /* OneTouch 8100 EPP/USB */
+               { 0x04a7, 0x0331 },     /* OneTouch 8600 EPP/USB */
 };
 
 /* Forward declarations */

Reply via email to