LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Linux - Hardware (http://www.linuxquestions.org/questions/linux-hardware-18/)
-   -   reading mouse movement (http://www.linuxquestions.org/questions/linux-hardware-18/reading-mouse-movement-451908/)

jdhar 06-05-2006 05:34 PM

reading mouse movement
 
i am trying to find resources on how to access mouse movement values through C, without using GPM. I am developing in an embedded environment, and I have verified that the mouse is spitting back data by 'cat /dev/input/mice', however, I cannot find out how to interpret this data.

Anyone?

osor 06-05-2006 08:03 PM

Quote:

Originally Posted by jdhar
i am trying to find resources on how to access mouse movement values through C, without using GPM. I am developing in an embedded environment, and I have verified that the mouse is spitting back data by 'cat /dev/input/mice', however, I cannot find out how to interpret this data.

Anyone?

Interesting problem. A preliminary look tells us that data is transferred three bytes at a time (on my machine). This was found through the output of
Code:

$ xxd -b -c 3 /dev/input/mice
Snooping around the kernel, we find this interesting function in linux/drivers/input/mousedev.c
Code:

static void mousedev_packet(struct mousedev_list *list, signed char *ps2_data)
{
        struct mousedev_motion *p;
        unsigned long flags;

        spin_lock_irqsave(&list->packet_lock, flags);
        p = &list->packets[list->tail];

        ps2_data[0] = 0x08 | ((p->dx < 0) << 4) | ((p->dy < 0) << 5) | (p->buttons & 0x07);
        ps2_data[1] = mousedev_limit_delta(p->dx, 127);
        ps2_data[2] = mousedev_limit_delta(p->dy, 127);
        p->dx -= ps2_data[1];
        p->dy -= ps2_data[2];

        switch (list->mode) {
                case MOUSEDEV_EMUL_EXPS:
                        ps2_data[3] = mousedev_limit_delta(p->dz, 7);
                        p->dz -= ps2_data[3];
                        ps2_data[3] = (ps2_data[3] & 0x0f) | ((p->buttons & 0x18) << 1);
                        list->bufsiz = 4;
                        break;

                case MOUSEDEV_EMUL_IMPS:
                        ps2_data[0] |= ((p->buttons & 0x10) >> 3) | ((p->buttons & 0x08) >> 1);
                        ps2_data[3] = mousedev_limit_delta(p->dz, 127);
                        p->dz -= ps2_data[3];
                        list->bufsiz = 4;
                        break;

                case MOUSEDEV_EMUL_PS2:
                default:
                        ps2_data[0] |= ((p->buttons & 0x10) >> 3) | ((p->buttons & 0x08) >> 1);
                        p->dz = 0;
                        list->bufsiz = 3;
                        break;
        }

        if (!p->dx && !p->dy && !p->dz) {
                if (list->tail == list->head) {
                        list->ready = 0;
                        list->last_buttons = p->buttons;
                } else
                        list->tail = (list->tail + 1) % PACKET_QUEUE_LEN;
        }

        spin_unlock_irqrestore(&list->packet_lock, flags);
}

As one can clearly see, a default ps/2 mouse will have three bytes, the first of which seems to describe the buttons, the deltax, and deltay. The second and third look like absolute x and y positions on the console.

Will post after further investigation.

jdhar 06-05-2006 08:24 PM

Thanks for your reply! When investigating myself before, I did an 'cat /dev/input/mice > ./testfile', and then did a hexdump on the ./testfile. Unfortunately, nothing in there seemed to look like absolute coordinates. Are we looking at the same thing?

osor 06-05-2006 09:34 PM

First: if you try using xxd (i prefer this to hexdump) live (as you are moving around the mouse), how many columns of bytes is your data transmitted in? If what I think is correct, then it should be either 3 or 4 (mine is 3).

Also, I was wrong about the absolute coordinates. That should be `deltas' or coordinates relative to previous position (with an upper bound of 127). I am still not sure what coordinate space the kernel is using (I have a guess that it's the resolution set during the Configure -> Device Drivers -> Input device support -> Generic input layer -> Mouse interface (1024x768).

osor 06-06-2006 05:24 PM

Alright, I think I have most of it (if all you care about is two buttons and change in location). The data is distributed as three or four bytes at a time. The first byte is a bunch of flags:
Code:

0 0 0 0 1 0 0 0
^ ^ ^ ^ ^ ^ ^ ^
| | | | | | | |
a b c d e f g h

I do not know what bits a and b do. Bit e is always 1 and is used as a marker for the `first byte' of a message. Bit h is 1 if the left button is down and 0 if it is up. Likewise, bit g is for the right mouse button, and bit f is for the middle mouse button. Bit d is 1, iff the value stored in the next byte is negative. Bit c is 1, iff the value stored in the third byte is negative.

If you haven't already guessed, the second byte holds dx (the change in x). The format is tricky (a signed char). The third bit holds dy (as a signed char). There is no danger of overflow, since dx and dy are made sure not to exceed 127 in magnitude.

My guess is that the fourth byte (if it exists) is for a scroll wheel (dz).

A brief refresher on signed chars:
Code:

38 = 00100110
-38 = 11011001



All times are GMT -5. The time now is 04:09 PM.