/dev/psaux multiple reader

Florian Lohoff flo at rfc822.org
Thu Dec 28 21:20:54 CET 2000


Hi Crash^H^H^H^H^HTester,
ich habe mich eben masslos ueber den /dev/psaux schrott geaergert das
ich mit gpm und X nicht gleichzeitig das device nutzen kann. Normalerweise
benutze ich den gpm "repeater" mit "-R raw" was aber leider anscheinend
mit Wheelmaeusen nicht funktioniert (Zumindest nicht mit dem USB testexemplar)

Ich habe denn mal in driver/char/pc_keyb.c gebastelt und dabei
ist der anhaengende patch rausgekommen. Fuer micht (ThinkPad T21,
gpm und XFree 3.3.6) funktioniert das dingen so - D.h. ich kann /dev/psaux
dann mehrfach oeffnen und bekomme auf ALLEN Filedescriptoren die
Daten. Kann die Testgruppe das bitte mal ausprobieren und am liebsten
waeren mir noch leute mit einer PS/2 Wheelmouse. D.h. X mit "ImPS/2" und
Zaxis auf /dev/psaux setzen und ebenso den gpm mit ps2 auf /dev/psaux
setzen. Ich habe die boese befuerchtung das die wheelmaeuse um die
Z Achse zu senden noch initialisierungsbefehle brauchen die dann den
GPM durcheinander bringen. D.h. startet X mit "ImPS/2" versucht der
die Maus auf 3D umzustellen was dann den gpm der 2D koordinaten erwarten
durcheinander bringt. Kann das mal wer testen ?

Der patch ist gegen 2.2.18 

Flo (Der auch ne wheelmouse brauch)
-- 
Florian Lohoff                  flo at rfc822.org             +49-5201-669912
     Why is it called "common sense" when nobody seems to have any?
-------------- next part --------------
--- pc_keyb.c	Thu Dec 28 16:55:48 2000
+++ linux/drivers/char/pc_keyb.c	Thu Dec 28 21:12:05 2000
@@ -13,6 +13,9 @@
  * Code fixes to handle mouse ACKs properly.
  * C. Scott Ananian <cananian at alumni.princeton.edu> 1999-01-29.
  *
+ * Multiple reader support
+ * Florian Lohoff <flo at rfc822.org> 2000-12-28
+ *
  */
 
 #include <linux/config.h>
@@ -403,7 +406,6 @@
 	
 	else if(scancode == AUX_RECONNECT && aux_reconnect)
 	{
-	        queue->head = queue->tail = 0;  /* Flush input queue */
         	/* ping the mouse :) */
 		kb_wait();
 		kbd_write_command(KBD_CCMD_WRITE_MOUSE);
@@ -417,16 +419,14 @@
 
 	add_mouse_randomness(scancode);
 	if (aux_count) {
-		int head = queue->head;
 
-		queue->buf[head] = scancode;
-		head = (head + 1) & (AUX_BUF_SIZE-1);
-		if (head != queue->tail) {
-			queue->head = head;
-			if (queue->fasync)
-				kill_fasync(queue->fasync, SIGIO);
-			wake_up_interruptible(&queue->proc_list);
-		}
+		queue->buf[queue->head & (AUX_BUF_SIZE-1)] = scancode;
+		queue->head++;
+
+		if (queue->fasync)
+			kill_fasync(queue->fasync, SIGIO);
+
+		wake_up_interruptible(&queue->proc_list);
 	}
 #endif
 }
@@ -837,24 +837,6 @@
 	spin_unlock_irqrestore(&kbd_controller_lock, flags);
 }
 
-static unsigned char get_from_queue(void)
-{
-	unsigned char result;
-	unsigned long flags;
-
-	spin_lock_irqsave(&kbd_controller_lock, flags);
-	result = queue->buf[queue->tail];
-	queue->tail = (queue->tail + 1) & (AUX_BUF_SIZE-1);
-	spin_unlock_irqrestore(&kbd_controller_lock, flags);
-	return result;
-}
-
-
-static inline int queue_empty(void)
-{
-	return queue->head == queue->tail;
-}
-
 static int fasync_aux(int fd, struct file *filp, int on)
 {
 	int retval;
@@ -865,7 +847,6 @@
 	return 0;
 }
 
-
 /*
  * Random magic cookie for the aux device
  */
@@ -882,6 +863,18 @@
 	return 0;
 }
 
+static long long gethead_aux(void )
+{
+	long long head;
+	unsigned long flags;
+
+	spin_lock_irqsave(&kbd_controller_lock, flags);
+	head=queue->head;	
+	spin_unlock_irqrestore(&kbd_controller_lock, flags);
+
+	return head;
+}
+
 /*
  * Install interrupt handler.
  * Enable auxiliary device.
@@ -890,13 +883,18 @@
 static int open_aux(struct inode * inode, struct file * file)
 {
 	if (aux_count++) {
+		/* We start where we are */
+		file->f_pos=gethead_aux();
 		return 0;
 	}
-	queue->head = queue->tail = 0;		/* Flush input queue */
+	/* First open - Begin at 0 */
+	queue->head=0;
+
 	if (aux_request_irq(keyboard_interrupt, AUX_DEV)) {
 		aux_count--;
 		return -EBUSY;
 	}
+
 	kbd_write_command_w(KBD_CCMD_MOUSE_ENABLE);	/* Enable the
 							   auxiliary port on
 							   controller. */
@@ -914,33 +912,57 @@
 			size_t count, loff_t *ppos)
 {
 	struct wait_queue wait = { current, NULL };
-	ssize_t i = count;
+	ssize_t i = 0;
 	unsigned char c;
+	long long head;
+	unsigned long flags;
+
+	if (*ppos >= gethead_aux()) {
 
-	if (queue_empty()) {
 		if (file->f_flags & O_NONBLOCK)
 			return -EAGAIN;
+
 		add_wait_queue(&queue->proc_list, &wait);
 repeat:
 		current->state = TASK_INTERRUPTIBLE;
-		if (queue_empty() && !signal_pending(current)) {
+		if (*ppos >= gethead_aux() && !signal_pending(current)) {
 			schedule();
 			goto repeat;
 		}
 		current->state = TASK_RUNNING;
 		remove_wait_queue(&queue->proc_list, &wait);
 	}
-	while (i > 0 && !queue_empty()) {
-		c = get_from_queue();
+
+	while(i < count) {
+
+		spin_lock_irqsave(&kbd_controller_lock, flags);
+
+		head=queue->head;
+		c=queue->buf[(*ppos+i) & (AUX_BUF_SIZE - 1)];
+
+		spin_unlock_irqrestore(&kbd_controller_lock, flags);
+
+		/* FIXME: Was reader too slow ? */
+		if (head-*ppos > AUX_BUF_SIZE)
+			return -EIO;
+
 		put_user(c, buffer++);
-		i--;
+
+		i++;
+
+		if (*ppos+i >= head)
+			break;
 	}
-	if (count-i) {
+
+	if (i) {
 		file->f_dentry->d_inode->i_atime = CURRENT_TIME;
-		return count-i;
+		*ppos+=i;
+		return i;
 	}
+
 	if (signal_pending(current))
 		return -ERESTARTSYS;
+
 	return 0;
 }
 
@@ -977,7 +999,7 @@
 static unsigned int aux_poll(struct file *file, poll_table * wait)
 {
 	poll_wait(file, &queue->proc_list, wait);
-	if (!queue_empty())
+	if (file->f_pos < gethead_aux())
 		return POLLIN | POLLRDNORM;
 	return 0;
 }
@@ -1012,7 +1034,7 @@
 	misc_register(&psaux_mouse);
 	queue = (struct aux_queue *) kmalloc(sizeof(*queue), GFP_KERNEL);
 	memset(queue, 0, sizeof(*queue));
-	queue->head = queue->tail = 0;
+	queue->head = 0;
 	queue->proc_list = NULL;
 
 #ifdef INITIALIZE_MOUSE


More information about the Linux mailing list