/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