patch-2.4.19 linux-2.4.19/drivers/char/ppdev.c

Next file: linux-2.4.19/drivers/char/pty.c
Previous file: linux-2.4.19/drivers/char/pcwd.c
Back to the patch index
Back to the overall index

diff -urN linux-2.4.18/drivers/char/ppdev.c linux-2.4.19/drivers/char/ppdev.c
@@ -4,7 +4,7 @@
  * This is the code behind /dev/parport* -- it allows a user-space
  * application to use the parport subsystem.
  *
- * Copyright (C) 1998-2000 Tim Waugh <tim@cyberelk.demon.co.uk>
+ * Copyright (C) 1998-2000, 2002 Tim Waugh <tim@cyberelk.net>
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
@@ -80,6 +80,7 @@
 	unsigned char irqctl;
 	struct ieee1284_info state;
 	struct ieee1284_info saved_state;
+	long default_inactivity;
 };
 
 /* pp_struct.flags bitfields */
@@ -107,7 +108,6 @@
 	struct pp_struct *pp = file->private_data;
 	char * kbuffer;
 	ssize_t bytes_read = 0;
-	ssize_t got = 0;
 	struct parport *pport;
 	int mode;
 
@@ -118,6 +118,10 @@
 		return -EINVAL;
 	}
 
+	/* Trivial case. */
+	if (count == 0)
+		return 0;
+
 	kbuffer = kmalloc(min_t(size_t, count, PP_BUFFER_SIZE), GFP_KERNEL);
 	if (!kbuffer) {
 		return -ENOMEM;
@@ -125,8 +129,13 @@
 	pport = pp->pdev->port;
 	mode = pport->ieee1284.mode & ~(IEEE1284_DEVICEID | IEEE1284_ADDR);
 
-	while (bytes_read < count) {
-		ssize_t need = min_t(unsigned long, count - bytes_read, PP_BUFFER_SIZE);
+	parport_set_timeout (pp->pdev,
+			     (file->f_flags & O_NONBLOCK) ?
+			     PARPORT_INACTIVITY_O_NONBLOCK :
+			     pp->default_inactivity);
+
+	while (bytes_read == 0) {
+		ssize_t need = min_t(unsigned long, count, PP_BUFFER_SIZE);
 
 		if (mode == IEEE1284_MODE_EPP) {
 			/* various specials for EPP mode */
@@ -144,37 +153,33 @@
 			} else {
 				fn = pport->ops->epp_read_data;
 			}
-			got = (*fn)(pport, kbuffer, need, flags);
+			bytes_read = (*fn)(pport, kbuffer, need, flags);
 		} else {
-			got = parport_read (pport, kbuffer, need);
+			bytes_read = parport_read (pport, kbuffer, need);
 		}
 
-		if (got <= 0) {
-			if (!bytes_read) {
-				bytes_read = got;
-			}
+		if (bytes_read != 0)
 			break;
-		}
 
-		if (copy_to_user (buf + bytes_read, kbuffer, got)) {
-			bytes_read = -EFAULT;
+		if (file->f_flags & O_NONBLOCK) {
+			bytes_read = -EAGAIN;
 			break;
 		}
 
-		bytes_read += got;
-
 		if (signal_pending (current)) {
-			if (!bytes_read) {
-				bytes_read = -EINTR;
-			}
+			bytes_read = -ERESTARTSYS;
 			break;
 		}
 
-		if (current->need_resched) {
+		if (current->need_resched)
 			schedule ();
-		}
 	}
 
+	parport_set_timeout (pp->pdev, pp->default_inactivity);
+
+	if (bytes_read > 0 && copy_to_user (buf, kbuffer, bytes_read))
+		bytes_read = -EFAULT;
+
 	kfree (kbuffer);
 	pp_enable_irq (pp);
 	return bytes_read;
@@ -205,6 +210,11 @@
 	pport = pp->pdev->port;
 	mode = pport->ieee1284.mode & ~(IEEE1284_DEVICEID | IEEE1284_ADDR);
 
+	parport_set_timeout (pp->pdev,
+			     (file->f_flags & O_NONBLOCK) ?
+			     PARPORT_INACTIVITY_O_NONBLOCK :
+			     pp->default_inactivity);
+
 	while (bytes_written < count) {
 		ssize_t n = min_t(unsigned long, count - bytes_written, PP_BUFFER_SIZE);
 
@@ -235,6 +245,12 @@
 
 		bytes_written += wrote;
 
+		if (file->f_flags & O_NONBLOCK) {
+			if (!bytes_written)
+				bytes_written = -EAGAIN;
+			break;
+		}
+
 		if (signal_pending (current)) {
 			if (!bytes_written) {
 				bytes_written = -EINTR;
@@ -247,6 +263,8 @@
 		}
 	}
 
+	parport_set_timeout (pp->pdev, pp->default_inactivity);
+
 	kfree (kbuffer);
 	pp_enable_irq (pp);
 	return bytes_written;
@@ -356,6 +374,8 @@
 		pp->saved_state.phase = info->phase;
 		info->mode = pp->state.mode;
 		info->phase = pp->state.phase;
+		pp->default_inactivity = parport_set_timeout (pp->pdev, 0);
+		parport_set_timeout (pp->pdev, pp->default_inactivity);
 
 		return 0;
 	    }

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)