Hi,
On Tue, Nov 12, 2002 at 11:59:02PM -0800, Greg KH wrote:
> > I think that's a rather low-risk patch that can be applied. That's why
> > I splitted it from the patch that fixes the "two-endpoints-only" issue
> > and the "can't unload" issue of the scanner driver (posted earlier on
> > linux-usb-devel).
>
> Mind sending me a copy of these patches again? It doesn't seem like
> Brian is very responsive lately...
Ok, here it is. Most of the code is from Sergey Vlasov
<[EMAIL PROTECTED]>. I've increased the version number, brought the
version number used in scanner.h in sync, added a ChangeLog entry
(including the previous vendor/device id additions).
I can't comment on the way, how the bugs are fixed in this patch
because I just don't know enough of kernel programming. However, the
code works for me and other users since some weeks without any
problem. It fixes the following bugs:
- can't rmmod scanner, because usage_count isn't 0 (especially if the
scanner was disconnected during scan)
- scanning for devices takes very long (now down from 25 seconds to
0.5 seconds with sane-1.0.9)
- lots of "Unable to access minor data" syslog messages are printed
when scanning for devices
- only scanners with a bulk-out endpoint are supported
Bye,
Henning
diff -u -r linux-2.4.20-rc1/drivers/usb/scanner.c
linux-2.4.20-rc1-compile/drivers/usb/scanner.c
--- linux-2.4.20-rc1/drivers/usb/scanner.c 2002-11-07 13:45:15.000000000 +0100
+++ linux-2.4.20-rc1-compile/drivers/usb/scanner.c 2002-11-13 15:58:24.000000000
++0100
@@ -1,7 +1,7 @@
/* -*- linux-c -*- */
/*
- * Driver for USB Scanners (linux-2.4.18)
+ * Driver for USB Scanners (linux-2.4.21)
*
* Copyright (C) 1999, 2000, 2001, 2002 David E. Nelson
*
@@ -311,8 +311,17 @@
* - Changed maintainership from David E. Nelson to Brian
* Beattie <[EMAIL PROTECTED]>.
*
+ * 0.4.9 11/13/2002
+ * - Added some Mustek BearPaw and Lexmark IDs (from Henning
+ * Meier-Geinitz <[EMAIL PROTECTED]>),
+ * - Support for scanners without bulk-out endpoint (from Sergey
+ * Vlasov <[EMAIL PROTECTED]>).
+ * - Fixed wrong usage count when devices were disconnected while opened
+ * (from Sergey Vlasov <[EMAIL PROTECTED]>).
+ * - "Unable to access minor data" is only a dbg message now and doesn't
+ * clutter syslog.
+ *
* TODO
- * - Remove the 2/3 endpoint limitation
* - Performance
* - Select/poll methods
* - More testing
@@ -349,6 +358,21 @@
*/
#include "scanner.h"
+static void usb_scanner_free(struct scn_usb_data *scn);
+
+static inline void
+usb_scanner_inc_use(struct scn_usb_data *scn)
+{
+ atomic_inc(&scn->users);
+}
+
+static inline void
+usb_scanner_dec_use(struct scn_usb_data *scn)
+{
+ if (atomic_dec_and_test(&scn->users))
+ usb_scanner_free(scn);
+}
+
static void
irq_scanner(struct urb *urb)
{
@@ -386,26 +410,33 @@
MOD_INC_USE_COUNT;
- down(&scn_mutex);
-
scn_minor = USB_SCN_MINOR(inode);
dbg("open_scanner: scn_minor:%d", scn_minor);
- if (!p_scn_table[scn_minor]) {
+ if (down_interruptible(&scn_mutex) != 0) {
+ MOD_DEC_USE_COUNT;
+ return -ERESTARTSYS;
+ }
+
+ scn = p_scn_table[scn_minor];
+ if (!scn) {
up(&scn_mutex);
MOD_DEC_USE_COUNT;
- err("open_scanner(%d): Unable to access minor data", scn_minor);
+ dbg("open_scanner(%d): Unable to access minor data", scn_minor);
return -ENODEV;
}
- scn = p_scn_table[scn_minor];
+ usb_scanner_inc_use(scn); /* Make sure the device won't go away */
- dev = scn->scn_dev;
+ up(&scn_mutex); /* Now handled by the above */
- down(&(scn->sem)); /* Now protect the scn_usb_data structure */
+ if (down_interruptible(&(scn->open_sem)) != 0) {
+ err = -ERESTARTSYS;
+ goto out_error_nounlock;
+ }
- up(&scn_mutex); /* Now handled by the above */
+ dev = scn->scn_dev;
if (!dev) {
err("open_scanner(%d): Scanner device not present", scn_minor);
@@ -433,11 +464,13 @@
out_error:
+ up(&(scn->open_sem)); /* Wake up any possible contending processes */
- up(&(scn->sem)); /* Wake up any possible contending processes */
-
- if (err)
+out_error_nounlock:
+ if (err) {
+ usb_scanner_dec_use(scn);
MOD_DEC_USE_COUNT;
+ }
return err;
}
@@ -447,27 +480,15 @@
{
struct scn_usb_data *scn;
- kdev_t scn_minor;
-
- scn_minor = USB_SCN_MINOR (inode);
-
- dbg("close_scanner: scn_minor:%d", scn_minor);
-
- if (!p_scn_table[scn_minor]) {
- err("close_scanner(%d): invalid scn_minor", scn_minor);
- return -ENODEV;
- }
+ scn = file->private_data;
- down(&scn_mutex);
+ dbg("close_scanner: scn_minor:%d", scn->scn_minor);
- scn = p_scn_table[scn_minor];
- down(&(scn->sem));
scn->isopen = 0;
file->private_data = NULL;
- up(&scn_mutex);
- up(&(scn->sem));
+ usb_scanner_dec_use(scn);
MOD_DEC_USE_COUNT;
@@ -494,7 +515,14 @@
scn = file->private_data;
- down(&(scn->sem));
+ if (down_interruptible(&(scn->sem)) != 0)
+ return -ERESTARTSYS;
+
+ if (!scn->bulk_out_ep) {
+ /* This scanner does not have a bulk-out endpoint */
+ up(&(scn->sem));
+ return -EINVAL;
+ }
scn_minor = scn->scn_minor;
@@ -582,7 +610,8 @@
scn = file->private_data;
- down(&(scn->sem));
+ if (down_interruptible(&(scn->sem)) != 0)
+ return -ERESTARTSYS;
scn_minor = scn->scn_minor;
@@ -684,18 +713,14 @@
ioctl_scanner(struct inode *inode, struct file *file,
unsigned int cmd, unsigned long arg)
{
+ struct scn_usb_data *scn;
struct usb_device *dev;
kdev_t scn_minor;
- scn_minor = USB_SCN_MINOR(inode);
-
- if (!p_scn_table[scn_minor]) {
- err("ioctl_scanner(%d): invalid scn_minor", scn_minor);
- return -ENODEV;
- }
-
- dev = p_scn_table[scn_minor]->scn_dev;
+ scn = file->private_data;
+ dev = scn->scn_dev;
+ scn_minor = scn->scn_minor;
switch (cmd)
{
@@ -902,8 +927,8 @@
dbg("probe_scanner: Number of Endpoints:%d", (int) interface->bNumEndpoints);
- if ((interface->bNumEndpoints != 2) && (interface->bNumEndpoints != 3)) {
- info("probe_scanner: Only two or three endpoints supported.");
+ if ((interface->bNumEndpoints < 1) || (interface->bNumEndpoints > 3)) {
+ info("probe_scanner: Only 1, 2, or 3 endpoints supported.");
return NULL;
}
@@ -942,6 +967,12 @@
*/
switch(interface->bNumEndpoints) {
+ case 1:
+ if (!have_bulk_in) {
+ info("probe_scanner: One bulk-in endpoint required.");
+ return NULL;
+ }
+ break;
case 2:
if (!have_bulk_in || !have_bulk_out) {
info("probe_scanner: Two bulk endpoints required.");
@@ -974,7 +1005,7 @@
}
/* Check to make sure that the last slot isn't already taken */
- if (p_scn_table[scn_minor]) {
+ if (scn_minor >= SCN_MAX_MNR) {
err("probe_scanner: No more minor devices remaining.");
up(&scn_mutex);
return NULL;
@@ -989,6 +1020,8 @@
}
memset (scn, 0, sizeof(struct scn_usb_data));
+ atomic_set(&scn->users, 1);
+ init_MUTEX(&(scn->open_sem));
init_MUTEX(&(scn->sem)); /* Initializes to unlocked */
dbg ("probe_scanner(%d): Address of scn:%p", scn_minor, scn);
@@ -1054,6 +1087,7 @@
scn->intr_ep = have_intr;
scn->present = 1;
scn->scn_dev = dev;
+ usb_inc_dev_use(dev);
scn->scn_minor = scn_minor;
scn->isopen = 0;
@@ -1075,29 +1109,37 @@
}
static void
-disconnect_scanner(struct usb_device *dev, void *ptr)
+usb_scanner_free(struct scn_usb_data *scn)
{
- struct scn_usb_data *scn = (struct scn_usb_data *) ptr;
-
- down (&scn_mutex);
- down (&(scn->sem));
+ dbg("usb_scanner_free(%d): freeing scn=%p", scn->scn_minor, scn);
if(scn->intr_ep) {
dbg("disconnect_scanner(%d): Unlinking IRQ URB", scn->scn_minor);
usb_unlink_urb(&scn->scn_irq);
}
- usb_driver_release_interface(&scanner_driver,
- &scn->scn_dev->actconfig->interface[scn->ifnum]);
+ usb_dec_dev_use(scn->scn_dev);
kfree(scn->ibuf);
kfree(scn->obuf);
+ kfree (scn);
+}
+
+static void
+disconnect_scanner(struct usb_device *dev, void *ptr)
+{
+ struct scn_usb_data *scn = (struct scn_usb_data *) ptr;
+
+ down (&scn_mutex);
+ usb_driver_release_interface(&scanner_driver,
+ &scn->scn_dev->actconfig->interface[scn->ifnum]);
+
dbg("disconnect_scanner: De-allocating minor:%d", scn->scn_minor);
devfs_unregister(scn->devfs);
p_scn_table[scn->scn_minor] = NULL;
- up (&(scn->sem));
- kfree (scn);
up (&scn_mutex);
+
+ usb_scanner_dec_use(scn);
}
static struct
Nur in linux-2.4.20-rc1-compile/drivers/usb/: scanner.c~.
diff -u -r linux-2.4.20-rc1/drivers/usb/scanner.h
linux-2.4.20-rc1-compile/drivers/usb/scanner.h
--- linux-2.4.20-rc1/drivers/usb/scanner.h 2002-11-07 13:45:15.000000000 +0100
+++ linux-2.4.20-rc1-compile/drivers/usb/scanner.h 2002-11-13 15:47:40.000000000
++0100
@@ -1,5 +1,5 @@
/*
- * Driver for USB Scanners (linux-2.4.18)
+ * Driver for USB Scanners (linux-2.4.21)
*
* Copyright (C) 1999, 2000, 2001, 2002 David E. Nelson
*
@@ -41,7 +41,7 @@
*/
// #define PV8630
-#define DRIVER_VERSION "0.4.6"
+#define DRIVER_VERSION "0.4.9"
#define DRIVER_DESC "USB Scanner Driver"
#include <linux/usb.h>
@@ -249,6 +249,7 @@
static DECLARE_MUTEX (scn_mutex); /* Initializes to unlocked */
struct scn_usb_data {
+ atomic_t users; /* Reference count */
struct usb_device *scn_dev;
devfs_handle_t devfs; /* devfs device */
struct urb scn_irq;
@@ -260,6 +261,7 @@
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 open_sem; /* lock to prevent concurrent opens */
struct semaphore sem; /* lock to prevent concurrent reads or writes */
unsigned int rd_nak_timeout; /* Seconds to wait before read() timeout. */
};
-------------------------------------------------------
This sf.net email is sponsored by: Are you worried about
your web server security? Click here for a FREE Thawte
Apache SSL Guide and answer your Apache SSL security
needs: http://www.gothawte.com/rd523.html
_______________________________________________
[EMAIL PROTECTED]
To unsubscribe, use the last form field at:
https://lists.sourceforge.net/lists/listinfo/linux-usb-devel