This patch corrects a bug produced by the weird logic in the "usblp_write" function. The patch applies cleanly against a vanilla 2.6.0 kernel, and already has the return codes correction proposed by me and Oliver Neukum.
This functions used the "usblp->writeurb->transfer_buffer_length" before initializing it.
With an application using non-blocking I/O and a printer going online/offline I could systematically reproduce a bug that makes the driver print endless garbage (the garbage appears to come from user space data).
With this patch, the logic becomes clearer and the bug goes away (tested).
-- Paulo Marques - www.grupopie.com
"In a world without walls and fences who needs windows and gates?"
--- drivers/usb/class/usblp.ori Tue Dec 30 18:52:19 2003
+++ drivers/usb/class/usblp.c Tue Dec 30 18:53:31 2003
@@ -603,14 +603,14 @@
{
DECLARE_WAITQUEUE(wait, current);
struct usblp *usblp = file->private_data;
- int timeout, err = 0;
+ int timeout, err = 0, transfer_length;
size_t writecount = 0;
while (writecount < count) {
if (!usblp->wcomplete) {
barrier();
if (file->f_flags & O_NONBLOCK)
- return -EAGAIN;
+ return writecount ? writecount : -EAGAIN;
timeout = USBLP_WRITE_TIMEOUT;
add_wait_queue(&usblp->wait, &wait);
@@ -654,31 +654,26 @@
continue;
}
- writecount += usblp->writeurb->transfer_buffer_length;
- usblp->writeurb->transfer_buffer_length = 0;
+ transfer_length = (count - writecount) < USBLP_BUF_SIZE ?
+ (count - writecount) : USBLP_BUF_SIZE;
- if (writecount == count) {
- up (&usblp->sem);
- break;
- }
+ usblp->writeurb->transfer_buffer_length = transfer_length;
- usblp->writeurb->transfer_buffer_length = (count - writecount) < USBLP_BUF_SIZE ?
- (count - writecount) : USBLP_BUF_SIZE;
-
- if (copy_from_user(usblp->writeurb->transfer_buffer, buffer + writecount,
- usblp->writeurb->transfer_buffer_length)) {
+ if (copy_from_user(usblp->writeurb->transfer_buffer, buffer + writecount, transfer_length)) {
up(&usblp->sem);
return writecount ? writecount : -EFAULT;
}
usblp->writeurb->dev = usblp->dev;
usblp->wcomplete = 0;
- if (usb_submit_urb(usblp->writeurb, GFP_KERNEL)) {
- count = -EIO;
+ if ((err = usb_submit_urb(usblp->writeurb, GFP_KERNEL))) {
+ count = err != -ENOMEM ? -EIO : (writecount ? writecount : -ENOMEM);
up (&usblp->sem);
break;
}
up (&usblp->sem);
+
+ writecount += transfer_length;
}
return count;
------------------------------------------------------- This SF.net email is sponsored by: IBM Linux Tutorials. Become an expert in LINUX or just sharpen your skills. Sign up for IBM's Free Linux Tutorials. Learn everything from the bash shell to sys admin. Click now! http://ads.osdn.com/?ad_id=1278&alloc_id=3371&op=click _______________________________________________ [EMAIL PROTECTED] To unsubscribe, use the last form field at: https://lists.sourceforge.net/lists/listinfo/linux-usb-devel