The following patch fixes "read_scanner(0): funky result:-75" errors which lead to application freeze and unusable scanner module until reboot. The bug was recently reported here for the Nikon LS-40, but I believe it also applieas to similar problems reported for Epson and Acer USB scanners over the past year on this list, sane-devel, and elsewhere.
Cause: read_scanner() sits in a loop, trying to bulk read all 'count' bytes of data. It erroneously decrements bytes remaining by 'this_read', what it asked for, instead of 'partial', what it got. For large reads (spanning multiple slow stepper-motor steps?) the scanner sometimes returns a short read, which makes 'count' shrink faster than it should, causing an attempt to read less than wMaxPacketSize bytes to be read before the last packet of the bulk transfer, causing EOVERFLOW. The conservative patch for 2.4.19 would be the following: --- linux-2.4.19/drivers/usb/scanner.c.orig Fri Oct 4 18:28:45 2002 +++ linux-2.4.19/drivers/usb/scanner.c Fri Oct 4 18:49:04 2002 @@ -653,7 +653,7 @@ ret = -EFAULT; break; } - count -= this_read; /* Compensate for short reads */ + count -= partial; /* Compensate for short reads */ bytes_read += partial; /* Keep tally of what actually was read */ buffer += partial; } else { =========================================================== However, I believe for 2.5 the loop should be rewritten as retry loop, and the function should immediately return whatever it reads, like the majority of drivers do. As a side effect, the number of retries on TIMEOUT/NAK would change, so the TIMEOUT values for various scanners would need to be retuned based on experience. For example, the following works fine for me under 2.4.19 (and also opens up opportunities for simplification of read_scanner()): --- linux-2.4.19/drivers/usb/scanner.c.orig Fri Oct 4 18:28:45 2002 +++ linux-2.4.19/drivers/usb/scanner.c Fri Oct 4 18:48:23 2002 @@ -553,13 +553,13 @@ struct scn_usb_data *scn; struct usb_device *dev; - ssize_t bytes_read; /* Overall count of bytes_read */ ssize_t ret; kdev_t scn_minor; int partial; /* Number of bytes successfully read */ int this_read; /* Max number of bytes to read */ + int retries; int result; int rd_expire = RD_EXPIRE; @@ -575,14 +575,14 @@ dev = scn->scn_dev; - bytes_read = 0; + retries = 3; ret = 0; file->f_dentry->d_inode->i_atime = CURRENT_TIME; /* Update the atime of the device node */ - while (count > 0) { + while (retries) { if (signal_pending(current)) { ret = -ERESTARTSYS; break; @@ -615,10 +615,11 @@ break; } else { /* Keep trying to read data */ interruptible_sleep_on_timeout(&scn->rd_wait_q, scn->rd_nak_timeout); + retries--; continue; } } else { /* Timeout w/ some data */ - goto data_recvd; + break; } } @@ -633,36 +634,31 @@ ret = -EIO; break; } - - data_recvd: + if (result == 0) { + break; + } + } #ifdef RD_DATA_DUMP - if (partial) { - unsigned char cnt, cnt_max; - cnt_max = (partial > 24) ? 24 : partial; - printk(KERN_DEBUG "dump(%d): ", scn_minor); - for (cnt=0; cnt < cnt_max; cnt++) { - printk("%X ", ibuf[cnt]); - } - printk("\n"); + if (partial) { + unsigned char cnt, cnt_max; + cnt_max = (partial > 24) ? 24 : partial; + printk(KERN_DEBUG "dump(%d): ", scn_minor); + for (cnt=0; cnt < cnt_max; cnt++) { + printk("%X ", ibuf[cnt]); } + printk("\n"); + } #endif - if (partial) { /* Data returned */ - if (copy_to_user(buffer, ibuf, partial)) { - ret = -EFAULT; - break; - } - count -= this_read; /* Compensate for short reads */ - bytes_read += partial; /* Keep tally of what actually was read */ - buffer += partial; - } else { - ret = 0; - break; + if (partial) { /* Data returned */ + if (copy_to_user(buffer, ibuf, partial)) { + ret = -EFAULT; } } + up(&(scn->sem)); - return ret ? ret : bytes_read; + return ret ? ret : partial; } static int =========================================================== -- ,_ /_) /| / / i e t e r / |/ a g e l http://www.nagel.co.za ------------------------------------------------------- This sf.net email is sponsored by:ThinkGeek Welcome to geek heaven. http://thinkgeek.com/sf _______________________________________________ [EMAIL PROTECTED] To unsubscribe, use the last form field at: https://lists.sourceforge.net/lists/listinfo/linux-usb-devel