Hi All,

As i saw the most of the mouse drivers are using busmouse.c as a base
module. I modified the pc_keyb.c to let the psaux device use the same
base as others (there is a q????? driver which could be modified this
way, but i can't test that).
Advantages:
- no queue buffer needed
- common base code with other drivers
- much less code in pc_keyb.c
- easier to detect reconnect because now it collects the 3 bytes input
so the previous bytes could be checked. The original handles all the
0xaa as a reconnect info but it could be a delta_x or a delta_y as well.
Disadvantages:
- pc_keyb.c compiled as built-in part of the kernel (keyboard of default
vga console, ...) so busmouse.c has to be compiled in instead of as a
kernel module.
- busmouse.c doesn't support reading less than 3 bytes (by the way, why
not? That would be closer to POSIX read standard, wouldn't it?) but the
current tools (X, gpm) read one byte at a time from the psaux device. So
i configured them to read from /dev/psaux but use busmouse protocol and
i added a code which translates from ps/2 to busmouse protocol. But this
way the ps/2 mouse could use the /dev/busmouse device file name (or what
it's name?) so it would be used as a real busmouse.

So if anyone thinks it is worth a try than test it and/or mail me what
You think about it.

The patch:
--- v2.4.0-test12/linux/drivers/char/pc_keyb.c  Mon Dec 18 13:37:16 2000
+++ linux/pc_keyb.c     Mon Dec 18 13:35:10 2000
@@ -13,9 +13,12 @@
  * Code fixes to handle mouse ACKs properly.
  * C. Scott Ananian <[EMAIL PROTECTED]> 1999-01-29.
  *
+ * Converted to use generic busmouse code.  13 Dec 2000
+ *   Balazs Kilvady <[EMAIL PROTECTED]>
  */
 
 #include <linux/config.h>
+#include <linux/module.h>
 
 #include <linux/spinlock.h>
 #include <linux/sched.h>
@@ -32,6 +35,7 @@
 #include <linux/malloc.h>
 #include <linux/kbd_kern.h>
 #include <linux/smp_lock.h>
+#include "busmouse.h"
 
 #include <asm/keyboard.h>
 #include <asm/bitops.h>
@@ -82,11 +86,14 @@
 
 #define AUX_RECONNECT 170 /* scancode when ps2 device is plugged (back)
in */
  
-static struct aux_queue *queue;        /* Mouse data buffer. */
 static int aux_count;
 /* used when we send commands to the mouse that expect an ACK. */
 static unsigned char mouse_reply_expected;
 
+static char tmp_byte[ 3 ];     /* byte buffer to collect a whole event */
+static int b_num;              /* position in tmp_byte */
+static int msedev;             /* busmouse device id */
+
 #define AUX_INTS_OFF (KBD_MODE_KCC | KBD_MODE_DISABLE_MOUSE |
KBD_MODE_SYS | KBD_MODE_KBD_INT)
 #define AUX_INTS_ON  (KBD_MODE_KCC | KBD_MODE_SYS | KBD_MODE_MOUSE_INT
| KBD_MODE_KBD_INT)
 
@@ -395,6 +402,8 @@
 static inline void handle_mouse_event(unsigned char scancode)
 {
 #ifdef CONFIG_PSMOUSE
+       static int is_recon;
+
        if (mouse_reply_expected) {
                if (scancode == AUX_ACK) {
                        mouse_reply_expected--;
@@ -402,23 +411,58 @@
                }
                mouse_reply_expected = 0;
        }
-       else if(scancode == AUX_RECONNECT){
-               queue->head = queue->tail = 0;  /* Flush input queue */
+
+       /*
+        * reconnect 'message' is 2 bytes long: 0xaa, 0x00
+        */
+       if (is_recon && scancode == '\0') {
+               printk(KERN_INFO "psmintr: reconnect catched at: %d, scode: 0x%02x,
prevs: %02x, %02x, %02x!\n",
+                       b_num,
+                       (unsigned)scancode,
+                       (unsigned)*((unsigned char *)tmp_byte),
+                       (unsigned)*((unsigned char *)(tmp_byte + 1)),
+                       (unsigned)*((unsigned char *)(tmp_byte + 2)));
+               is_recon = 0;
+               b_num = 0;
                aux_write_ack(AUX_ENABLE_DEV);  /* ping the mouse :) */
                return;
-       }
+       } else if (scancode == AUX_RECONNECT) {
+               is_recon = 1;
+               printk(KERN_INFO "psmintr: reconnect code at: %d\n", b_num);
+       } else
+               is_recon = 0;
 
        add_mouse_randomness(scancode);
        if (aux_count) {
-               int head = queue->head;
+               int button;
 
-               queue->buf[head] = scancode;
-               head = (head + 1) & (AUX_BUF_SIZE-1);
-               if (head != queue->tail) {
-                       queue->head = head;
-                       kill_fasync(&queue->fasync, SIGIO, POLL_IN);
-                       wake_up_interruptible(&queue->proc_list);
+               tmp_byte[ b_num ] = (signed char)scancode;
+               if (b_num < 2) {
+                       /*
+                        * first byte?
+                        */
+                       if (b_num != 0
+                               || (scancode & AUX_CHECK_BITS) == AUX_CHECK_RES)
+                               ++b_num;
+                       else
+                               printk(KERN_INFO "psmintr: it shouldn't happen, 0th 
+byte: 0x%02x,
prevs: %02x, %02x!\n",
+                                       (unsigned)scancode,
+                                       (unsigned)*((unsigned char *)(tmp_byte + 1)),
+                                       (unsigned)*((unsigned char *)(tmp_byte + 2)));
+                       return;
                }
+               b_num = 0;
+
+               /*
+                * translate to busmouse protocol
+                */
+               button = (int)(~tmp_byte[ 0 ]);
+               button = ((button >> 1) & 3) | ((button << 2) & 4);
+               busmouse_add_movementbuttons(
+                               msedev,
+                               (int)tmp_byte[ 1 ],
+                               (int)tmp_byte[ 2 ],
+                               button);
        }
 #endif
 }
@@ -801,21 +845,6 @@
 }
 
 /*
- * Send a byte to the mouse.
- */
-static void aux_write_dev(int val)
-{
-       unsigned long flags;
-
-       spin_lock_irqsave(&kbd_controller_lock, flags);
-       kb_wait();
-       kbd_write_command(KBD_CCMD_WRITE_MOUSE);
-       kb_wait();
-       kbd_write_output(val);
-       spin_unlock_irqrestore(&kbd_controller_lock, flags);
-}
-
-/*
  * Send a byte to the mouse & handle returned ack
  */
 static void aux_write_ack(int val)
@@ -833,44 +862,29 @@
        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;
-
-       retval = fasync_helper(fd, filp, on, &queue->fasync);
-       if (retval < 0)
-               return retval;
-       return 0;
-}
-
-
 /*
  * Random magic cookie for the aux device
  */
-#define AUX_DEV ((void *)queue)
+#define AUX_DEV ((void *)tmp_byte)
 
 static int release_aux(struct inode * inode, struct file * file)
 {
        lock_kernel();
-       fasync_aux(-1, file, 0);
+
+       /*
+        * temp checking: The mouse sends 3 bytes but we haven't read all of
it
+        * but close the device. It's (almost) sure that free_irq solves it,
+        * but... 
+        */
+       if (b_num != 0)
+               printk(KERN_INFO "release_aux: called when not at 3 bytes boundary,
b_num: %d\n",
+                       b_num);
+
+       /*
+        * fasync call commented out, it can be a problem but busmouse handles
+        * fasync things inside :-(
+        */
+       //fasync_aux(-1, file, 0);
        if (--aux_count) {
                unlock_kernel();
                return 0;
@@ -892,7 +906,14 @@
        if (aux_count++) {
                return 0;
        }
-       queue->head = queue->tail = 0;          /* Flush input queue */
+       /*
+        * temp checking: It can cause problem when more then one program
+        * read the device but it's not supported in busmouse
+        */
+       if (b_num != 0)
+               printk(KERN_INFO "open_aux: called when not at 3 bytes boundary,
b_num: %d\n",
+                       b_num);
+       b_num = 0;
        if (aux_request_irq(keyboard_interrupt, AUX_DEV)) {
                aux_count--;
                return -EBUSY;
@@ -909,96 +930,10 @@
 }
 
 /*
- * Put bytes from input queue to buffer.
- */
-
-static ssize_t read_aux(struct file * file, char * buffer,
-                       size_t count, loff_t *ppos)
-{
-       DECLARE_WAITQUEUE(wait, current);
-       ssize_t i = count;
-       unsigned char c;
-
-       if (queue_empty()) {
-               if (file->f_flags & O_NONBLOCK)
-                       return -EAGAIN;
-               add_wait_queue(&queue->proc_list, &wait);
-repeat:
-               set_current_state(TASK_INTERRUPTIBLE);
-               if (queue_empty() && !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();
-               put_user(c, buffer++);
-               i--;
-       }
-       if (count-i) {
-               file->f_dentry->d_inode->i_atime = CURRENT_TIME;
-               return count-i;
-       }
-       if (signal_pending(current))
-               return -ERESTARTSYS;
-       return 0;
-}
-
-/*
- * Write to the aux device.
- */
-
-static ssize_t write_aux(struct file * file, const char * buffer,
-                        size_t count, loff_t *ppos)
-{
-       ssize_t retval = 0;
-
-       if (count) {
-               ssize_t written = 0;
-
-               if (count > 32)
-                       count = 32; /* Limit to 32 bytes. */
-               do {
-                       char c;
-                       get_user(c, buffer++);
-                       aux_write_dev(c);
-                       written++;
-               } while (--count);
-               retval = -EIO;
-               if (written) {
-                       retval = written;
-                       file->f_dentry->d_inode->i_mtime = CURRENT_TIME;
-               }
-       }
-
-       return retval;
-}
-
-/* No kernel lock held - fine */
-static unsigned int aux_poll(struct file *file, poll_table * wait)
-{
-       poll_wait(file, &queue->proc_list, wait);
-       if (!queue_empty())
-               return POLLIN | POLLRDNORM;
-       return 0;
-}
-
-struct file_operations psaux_fops = {
-       read:           read_aux,
-       write:          write_aux,
-       poll:           aux_poll,
-       open:           open_aux,
-       release:        release_aux,
-       fasync:         fasync_aux,
-};
-
-/*
  * Initialize driver.
  */
-static struct miscdevice psaux_mouse = {
-       PSMOUSE_MINOR, "psaux", &psaux_fops
+static struct busmouse psaux_mouse = {
+       PSMOUSE_MINOR, "psaux", THIS_MODULE, open_aux, release_aux, 7
 };
 
 static int __init psaux_init(void)
@@ -1006,11 +941,8 @@
        if (!detect_auxiliary_port())
                return -EIO;
 
-       misc_register(&psaux_mouse);
-       queue = (struct aux_queue *) kmalloc(sizeof(*queue), GFP_KERNEL);
-       memset(queue, 0, sizeof(*queue));
-       queue->head = queue->tail = 0;
-       init_waitqueue_head(&queue->proc_list);
+       b_num = 0;
+       msedev = register_busmouse(&psaux_mouse);
 
 #ifdef INITIALIZE_MOUSE
        kbd_write_command_w(KBD_CCMD_MOUSE_ENABLE); /* Enable Aux. */
@@ -1023,7 +955,11 @@
        kbd_write_command(KBD_CCMD_MOUSE_DISABLE); /* Disable aux device. */
        kbd_write_cmd(AUX_INTS_OFF); /* Disable controller ints. */
 
-       return 0;
+       if (msedev < 0)
+               printk(KERN_WARNING "Unable to register psaux driver.\n");
+       else
+               printk(KERN_INFO "PS/2 mouse detected and installed.\n");
+       return msedev < 0 ? msedev : 0;
 }
 
 #endif /* CONFIG_PSMOUSE */
--- v2.4.0-test12/linux/include/linux/pc_keyb.h Mon Dec 18 13:37:33 2000
+++ linux/pc_keyb.h     Wed Dec 13 14:27:23 2000
@@ -115,16 +115,12 @@
 #define AUX_DISABLE_DEV                0xF5    /* Disable aux device */
 #define AUX_RESET              0xFF    /* Reset aux device */
 #define AUX_ACK                        0xFA    /* Command byte ACK. */
+#define AUX_CHECK_BITS         0xC8    /* At normal data C bits should be 0,
+                                          8 bit should be 1 */
+#define AUX_CHECK_RES          0x08
 
 #define AUX_BUF_SIZE           2048    /* This might be better divisible by
                                           three to make overruns stay in sync
                                           but then the read function would need
                                           a lock etc - ick */
 
-struct aux_queue {
-       unsigned long head;
-       unsigned long tail;
-       wait_queue_head_t proc_list;
-       struct fasync_struct *fasync;
-       unsigned char buf[AUX_BUF_SIZE];
-};
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [EMAIL PROTECTED]
Please read the FAQ at http://www.tux.org/lkml/

Reply via email to