[sane-devel] 44-10 vs epson 1250

Henning Meier-Geinitz henning@meier-geinitz.de
Fri, 18 Oct 2002 17:55:52 +0200


--T4sUOijqQbZv57TR
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline

Hi,

On Fri, Oct 18, 2002 at 05:25:44PM +0200, Till Kamppeter wrote:
> When I have only an Epson Perfection 1260 connected ("plustek" driver) 
> the "snapscan" backend takes around 15 seconds, with "snapscan" 
> commented out xsnae needs less than 10 seconds to start, with "snapscan" 
> around 25. "mustek-usb" is on the second place with something like two 
> seconds.

The USB detection funtion in sanei_usb isn't very effective.
For every sanei_usb_attach_matching_devices it checks all the
/dev/usb/scanner devices, opens them, sends the vendor/product id
ioctls and closes them. That's done for every scanner in the backend.
For a scanimage -L, about 1300 files are opened.

However, the real culprit seems to be the USB scanner driver:

Times for scanimage -L on my system with to Mustek USB scanners
attached:

* without scanner driver (with libusb):            0.437s
* with the scanner driver from Linux 2.4.20pre10: 19.385s

Now I'm using a patched kernel scanner driver that disables the
warning messages sent to syslog, fixes the "unable-to-rmmod" bug and
adds support for devices without bulk-out-endpoints:

* 0.437s

That's not a joke. I don't know which of the changes makes the
difference, but it works (and the annoying messages in syslog are
gone). The patch is from Sergey Vlasov and was already submitted to
the maintainer of the USB scanner module and the linux-usb-devel
mailinglist. They don't seem to be very interested until now, however.

Bye,
  Henning





--T4sUOijqQbZv57TR
Content-Type: video/x-dv
Content-Disposition: attachment; filename="scanner-endpoint.dif"
Content-Transfer-Encoding: quoted-printable

diff -ur linux-2.4.20-pre10/drivers/usb/scanner.c linux-2.4.20-pre10-patche=
d/drivers/usb/scanner.c=0A--- linux-2.4.20-pre10/drivers/usb/scanner.c	2002=
-10-12 13:40:01.000000000 +0200=0A+++ linux-2.4.20-pre10-patched/drivers/us=
b/scanner.c	2002-10-12 13:46:39.000000000 +0200=0A@@ -349,6 +349,21 @@=0A  =
*/ =0A #include "scanner.h"=0A =0A+static void usb_scanner_free(struct scn_=
usb_data *scn);=0A+=0A+static inline void=0A+usb_scanner_inc_use(struct scn=
_usb_data *scn)=0A+{=0A+	atomic_inc(&scn->users);=0A+}=0A+=0A+static inline=
 void=0A+usb_scanner_dec_use(struct scn_usb_data *scn)=0A+{=0A+	if (atomic_=
dec_and_test(&scn->users))=0A+		usb_scanner_free(scn);=0A+}=0A+=0A static v=
oid=0A irq_scanner(struct urb *urb)=0A {=0A@@ -386,26 +401,33 @@=0A =0A 	MO=
D_INC_USE_COUNT;=0A =0A-	down(&scn_mutex);=0A-=0A 	scn_minor =3D USB_SCN_MI=
NOR(inode);=0A =0A 	dbg("open_scanner: scn_minor:%d", scn_minor);=0A =0A-	i=
f (!p_scn_table[scn_minor]) {=0A+	if (down_interruptible(&scn_mutex) !=3D 0=
) {=0A+		MOD_DEC_USE_COUNT;=0A+		return -ERESTARTSYS;=0A+	}=0A+=0A+	scn =3D=
 p_scn_table[scn_minor];=0A+	if (!scn) {=0A 		up(&scn_mutex);=0A 		MOD_DEC_=
USE_COUNT;=0A-		err("open_scanner(%d): Unable to access minor data", scn_mi=
nor);=0A+		dbg("open_scanner(%d): Unable to access minor data", scn_minor);=
=0A 		return -ENODEV;=0A 	}=0A =0A-	scn =3D p_scn_table[scn_minor];=0A+	usb=
_scanner_inc_use(scn); /* Make sure the device won't go away */=0A =0A-	dev=
 =3D scn->scn_dev;=0A+	up(&scn_mutex); /* Now handled by the above */=0A =
=0A-	down(&(scn->sem));	/* Now protect the scn_usb_data structure */ =0A+	i=
f (down_interruptible(&(scn->open_sem)) !=3D 0) {=0A+		err =3D -ERESTARTSYS=
;=0A+		goto out_error_nounlock;=0A+	}=0A =0A-	up(&scn_mutex); /* Now handle=
d by the above */=0A+	dev =3D scn->scn_dev;=0A =0A 	if (!dev) {=0A 		err("o=
pen_scanner(%d): Scanner device not present", scn_minor);=0A@@ -433,11 +455=
,13 @@=0A =0A =0A out_error:=0A+	up(&(scn->open_sem)); /* Wake up any possi=
ble contending processes */=0A =0A-	up(&(scn->sem)); /* Wake up any possibl=
e contending processes */=0A-=0A-	if (err)=0A+out_error_nounlock:=0A+	if (e=
rr) {=0A+		usb_scanner_dec_use(scn);=0A 		MOD_DEC_USE_COUNT;=0A+	}=0A =0A 	=
return err;=0A }=0A@@ -447,27 +471,15 @@=0A {=0A 	struct scn_usb_data *scn;=
=0A =0A-	kdev_t scn_minor;=0A-=0A-	scn_minor =3D USB_SCN_MINOR (inode);=0A-=
=0A-	dbg("close_scanner: scn_minor:%d", scn_minor);=0A-=0A-	if (!p_scn_tabl=
e[scn_minor]) {=0A-		err("close_scanner(%d): invalid scn_minor", scn_minor)=
;=0A-		return -ENODEV;=0A-	}=0A+	scn =3D file->private_data;=0A =0A-	down(&=
scn_mutex);=0A+	dbg("close_scanner: scn_minor:%d", scn->scn_minor);=0A =0A-=
	scn =3D p_scn_table[scn_minor];=0A-	down(&(scn->sem));=0A 	scn->isopen =3D=
 0;=0A =0A 	file->private_data =3D NULL;=0A =0A-	up(&scn_mutex);=0A-	up(&(s=
cn->sem));=0A+	usb_scanner_dec_use(scn);=0A =0A 	MOD_DEC_USE_COUNT;=0A =0A@=
@ -494,7 +506,14 @@=0A =0A 	scn =3D file->private_data;=0A =0A-	down(&(scn-=
>sem));=0A+	if (down_interruptible(&(scn->sem)) !=3D 0)=0A+		return -ERESTA=
RTSYS;=0A+=0A+	if (!scn->bulk_out_ep) {=0A+		/* This scanner does not have =
a bulk-out endpoint */=0A+		up(&(scn->sem));=0A+		return -EINVAL;=0A+	}=0A =
=0A 	scn_minor =3D scn->scn_minor;=0A =0A@@ -582,7 +601,8 @@=0A =0A 	scn =
=3D file->private_data;=0A =0A-	down(&(scn->sem));=0A+	if (down_interruptib=
le(&(scn->sem)) !=3D 0)=0A+		return -ERESTARTSYS;=0A =0A 	scn_minor =3D scn=
->scn_minor;=0A =0A@@ -684,18 +704,14 @@=0A ioctl_scanner(struct inode *ino=
de, struct file *file,=0A 	      unsigned int cmd, unsigned long arg)=0A {=
=0A+	struct scn_usb_data *scn;=0A 	struct usb_device *dev;=0A =0A 	kdev_t s=
cn_minor;=0A =0A-	scn_minor =3D USB_SCN_MINOR(inode);=0A-=0A-	if (!p_scn_ta=
ble[scn_minor]) {=0A-		err("ioctl_scanner(%d): invalid scn_minor", scn_mino=
r);=0A-		return -ENODEV;=0A-	}=0A-=0A-	dev =3D p_scn_table[scn_minor]->scn_=
dev;=0A+	scn =3D file->private_data;=0A+	dev =3D scn->scn_dev;=0A+	scn_mino=
r =3D scn->scn_minor;=0A =0A 	switch (cmd)=0A 	{=0A@@ -902,8 +918,8 @@=0A =
=0A 	dbg("probe_scanner: Number of Endpoints:%d", (int) interface->bNumEndp=
oints);=0A =0A-	if ((interface->bNumEndpoints !=3D 2) && (interface->bNumEn=
dpoints !=3D 3)) {=0A-		info("probe_scanner: Only two or three endpoints su=
pported.");=0A+	if ((interface->bNumEndpoints < 1) || (interface->bNumEndpo=
ints > 3)) {=0A+		info("probe_scanner: Only 1, 2, or 3 endpoints supported.=
");=0A 		return NULL;=0A 	}=0A =0A@@ -942,6 +958,12 @@=0A  */=0A =0A 	switc=
h(interface->bNumEndpoints) {=0A+	case 1:=0A+		if (!have_bulk_in) {=0A+			i=
nfo("probe_scanner: One bulk-in endpoint required.");=0A+			return NULL;=0A=
+		}=0A+		break;=0A 	case 2:=0A 		if (!have_bulk_in || !have_bulk_out) {=0A=
 			info("probe_scanner: Two bulk endpoints required.");=0A@@ -974,7 +996,7=
 @@=0A 	}=0A =0A /* Check to make sure that the last slot isn't already tak=
en */=0A-	if (p_scn_table[scn_minor]) {=0A+	if (scn_minor >=3D SCN_MAX_MNR)=
 {=0A 		err("probe_scanner: No more minor devices remaining.");=0A 		up(&sc=
n_mutex);=0A 		return NULL;=0A@@ -989,6 +1011,8 @@=0A 	}=0A 	memset (scn, 0=
, sizeof(struct scn_usb_data));=0A =0A+	atomic_set(&scn->users, 1);=0A+	ini=
t_MUTEX(&(scn->open_sem));=0A 	init_MUTEX(&(scn->sem)); /* Initializes to u=
nlocked */=0A =0A 	dbg ("probe_scanner(%d): Address of scn:%p", scn_minor, =
scn);=0A@@ -1054,6 +1078,7 @@=0A 	scn->intr_ep =3D have_intr;=0A 	scn->pres=
ent =3D 1;=0A 	scn->scn_dev =3D dev;=0A+	usb_inc_dev_use(dev);=0A 	scn->scn=
_minor =3D scn_minor;=0A 	scn->isopen =3D 0;=0A =0A@@ -1075,29 +1100,37 @@=
=0A }=0A =0A static void=0A-disconnect_scanner(struct usb_device *dev, void=
 *ptr)=0A+usb_scanner_free(struct scn_usb_data *scn)=0A {=0A-	struct scn_us=
b_data *scn =3D (struct scn_usb_data *) ptr;=0A-=0A-	down (&scn_mutex);=0A-=
	down (&(scn->sem));=0A+	dbg("usb_scanner_free(%d): freeing scn=3D%p", scn-=
>scn_minor, scn);=0A =0A 	if(scn->intr_ep) {=0A 		dbg("disconnect_scanner(%=
d): Unlinking IRQ URB", scn->scn_minor);=0A 		usb_unlink_urb(&scn->scn_irq)=
;=0A 	}=0A-        usb_driver_release_interface(&scanner_driver,=0A-       =
         &scn->scn_dev->actconfig->interface[scn->ifnum]);=0A =0A+	usb_dec_=
dev_use(scn->scn_dev);=0A 	kfree(scn->ibuf);=0A 	kfree(scn->obuf);=0A =0A+	=
kfree (scn);=0A+}=0A+=0A+static void=0A+disconnect_scanner(struct usb_devic=
e *dev, void *ptr)=0A+{=0A+	struct scn_usb_data *scn =3D (struct scn_usb_da=
ta *) ptr;=0A+=0A+	down (&scn_mutex);=0A+        usb_driver_release_interfa=
ce(&scanner_driver,=0A+                &scn->scn_dev->actconfig->interface[=
scn->ifnum]);=0A+=0A 	dbg("disconnect_scanner: De-allocating minor:%d", scn=
->scn_minor);=0A 	devfs_unregister(scn->devfs);=0A 	p_scn_table[scn->scn_mi=
nor] =3D NULL;=0A-	up (&(scn->sem));=0A-	kfree (scn);=0A 	up (&scn_mutex);=
=0A+=0A+	usb_scanner_dec_use(scn);=0A }=0A =0A static struct=0Adiff -ur lin=
ux-2.4.20-pre10/drivers/usb/scanner.h linux-2.4.20-pre10-patched/drivers/us=
b/scanner.h=0A--- linux-2.4.20-pre10/drivers/usb/scanner.h	2002-10-12 13:40=
:01.000000000 +0200=0A+++ linux-2.4.20-pre10-patched/drivers/usb/scanner.h	=
2002-10-12 13:51:52.000000000 +0200=0A@@ -249,6 +249,7 @@=0A static DECLARE=
_MUTEX (scn_mutex); /* Initializes to unlocked */=0A =0A struct scn_usb_dat=
a {=0A+	atomic_t users;		/* Reference count */=0A 	struct usb_device *scn_d=
ev;=0A 	devfs_handle_t devfs;	/* devfs device */=0A 	struct urb scn_irq;=0A=
@@ -260,6 +261,7 @@=0A 	char *obuf, *ibuf;	/* transfer buffers */=0A 	char =
bulk_in_ep, bulk_out_ep, intr_ep; /* Endpoint assignments */=0A 	wait_queue=
_head_t rd_wait_q; /* read timeouts */=0A+	struct semaphore open_sem; /* lo=
ck to prevent concurrent opens */=0A 	struct semaphore sem; /* lock to prev=
ent concurrent reads or writes */=0A 	unsigned int rd_nak_timeout; /* Secon=
ds to wait before read() timeout. */=0A };=0A
--T4sUOijqQbZv57TR--