• 欢迎浏览“String me = Creater\忠实的资深Linux玩家;”,请文明浏览,理性发言,有侵犯你的权益请邮件我(creater@vip.qq.com).
  • 把任何的失败都当作一次尝试,不要自卑;把所有的成功都想成是一种幸运,不要自傲。
  •    6年前 (2013-05-14)  Linux Linux应用 Linux编程问题 |   抢沙发  9 
    文章评分 0 次,平均分 0.0

    1. 关于"/dev/input/mice"
    相信很多人都用过Linux,也许你发现不管是在X-window下面,还是在Console下面,鼠标都是可以操作的。那么你有没有考虑过这些鼠标都是从哪来的?

    不错!他们都是从"/dev/input/mice"这个文件里来的。如果你对Linux比较熟,那么你肯定看得出来这是一个设备文件。"mice"就是Linux下面鼠标的设备文件,不管你用的是PS2的还是USB的,所有关于鼠标的操作都被抽象到"mice"这个文件中。

    2. "mice"之母
    在linux下面,她是"mousedev.c"这个文件。你可以在内核的"Drivers/input"目录里找到她。在她那里,你可以得到关于"mice"的一切。

    3. 坐标
    如何得到mouse的当前坐标值?可通过如下几步:

    1)打开"/dev/input/mice"文件。

    2)读3个字节。三个字节的值分别是“Button类型”,“X的相对位移”,“Y的相对位移”。这里先用Button, xRel, yRel表示。

    3)取Button的低3位(Button & 0x07)。0x00 = LeftButtonUp, 0x01 = LeftButtonDown, 0x02 = RightButtonDown.

    4)因为这里取得是相对位移,所以X, Y要分别与上一次的坐标值相加。xPos += xRel; yPos +=yRel.

    好了,到这里完成了一次读取操作。具体的代码请参见附录一。附录二介绍一下gpm。

    我很奇怪为什么在网上找不到这方面的资料,关于gpm的资料也是寥寥无几。

    #include <stdio.h>
    #include <fcntl.h>
    #include <sys/time.h>
    #include <sys/types.h>
    #include <unistd.h>
    int main (int argc, char **argv)
    {
        int fd, retval;
        char buf[6];
        fd_set readfds;
        struct timeval tv;
        fd = open ("/dev/input/mice", O_RDONLY | O_NONBLOCK);
        if (fd < 0) {
            printf ("Failed to open /dev/input/mice /n");
            return -1;
        }
        printf ("Suceed to open /dev/input/mice.fd = %d/n", fd);
        tv.tv_sec = 5;
        tv.tv_usec = 0;
        while (1) {
            FD_ZERO (&readfds);
            FD_SET (fd, &readfds);
            retval = select (fd + 1, &readfds, NULL, NULL, &tv);
            printf ("retval = %d/n", retval);
            if (retval == 1) {
                printf ("select OK. /n");
                if (read (fd, buf, 6) <= 0) {
                    printf ("Fail to read. /n");
                    continue;
                }
                printf ("Button type = %d, X = %d, Y = %d./n",
                        buf[0] & 0x07, buf[1], buf[2]);
            }
        }
        close (fd);
        return 0;
    }

    附录二:
    gpm是linux console下的鼠标操作服务。用它可以实现copy和paste操作。你也可以用gpm提供的API得到鼠标的坐标。但这些API的原理也是跟上面讲的一样,都是操作mice文件。

        #include <stdio.h>  
        #include <errno.h>  
        #include <fcntl.h>  
        #include <sys/select.h>  
        #include <string.h>  
          
        /* Mouse button bits*/  
        #define WHEEL_UP 0x10  
        #define WHEEL_DOWN 0x08  
          
        #define BUTTON_L 0x04  
        #define BUTTON_M 0x02  
        #define BUTTON_R 0x01  
        #define SCALE 3 /* default scaling factor for acceleration */  
        #define THRESH 5 /* default threshhold for acceleration */  
          
        static int xpos; /* current x position of mouse */  
        static int ypos; /* current y position of mouse */  
        static int minx; /* minimum allowed x position */  
        static int maxx; /* maximum allowed x position */  
        static int miny; /* minimum allowed y position */  
        static int maxy; /* maximum allowed y position */  
        static int buttons; /* current state of buttons */  
        static int scale = SCALE; /* acceleration scale factor */  
        static int thresh = THRESH;/* acceleration threshhold */  
          
        static int mouse_update(int dx, int dy, int dz);  
        static int IMPS2_Read (int *dx, int *dy, int *dz, int *bp);  
        static void mouse_setposition (int newx, int newy);  
        static void mouse_setrange (int newminx, int newminy, int newmaxx, int newmaxy);  
          
        int mouse_fd;  
          
        int main(void)  
        {  
            int dx,dy,dz;  
            static unsigned char imps2_param [] = {243,200,243,100,243,80};//,242};  
            // 来自vnc4的xc/programs/Xserver/hw/xfree86/input/mouse/mouse.c==>PROT_IMPS2  
            const char *mdev="/dev/input/mice";  
          
             mouse_fd = open (mdev, O_RDWR); // | O_NONBLOCK);  
            if (mouse_fd < 0) {  
                printf("[luther.gliethttp]: RW error [please use root user]: %s\n", mdev);  
                 mouse_fd = open (mdev, O_RDONLY); // | O_NONBLOCK);  
                if (mouse_fd < 0)  
                    return -1;  
            } else {  
                write (mouse_fd, imps2_param, sizeof (imps2_param)); // 初始化序列, 这样可以读取4个字节数据  
                // 0x80用来表示滚轮向上还是向下滚动.de>  
          
                // 0xa0表示滚轮向上滚动的同时中键按下  
                 printf("[luther.gliethttp]: imps2_param ok!\n");  
            }  
              
             mouse_setrange(0, 0, 1024, 768);  
          
            for (;;) {  
                 IMPS2_Read(&dx, &dy, &dz, &buttons);  
                 mouse_update(dx, dy, dz);  
                 mouse_setposition(xpos, ypos);  
                printf("[%04d,%04d,0x%04x]\n", xpos, ypos, buttons);  
            }  
              
            return 0;  
        }  
          
        static int IMPS2_Read (int *dx, int *dy, int *dz, int *bp)  
        {  
            static unsigned char buf[5];  
            static int buttons[7] = { 0, 1, 3, 0, 2, 0, 0}; // 1左键,2中键,3右键  
            static int nbytes;  
            int n;  
          
            while ((n = read (mouse_fd, &buf [nbytes], 4 - nbytes))) {  
                if (n < 0) {  
                    if (errno == EINTR)  
                        continue;  
                    else  
                        return -1;  
                }  
          
                 nbytes += n;  
          
                if (nbytes == 4) {  
                    int wheel;  
                    // printf("[luther.gliethttp]: %02x %02x %02x %02x\n", buf[0], buf[1], buf[2], buf[3]);  
                    if ((buf[0] & 0xc0) != 0) {  
                         buf[0] = buf[1];  
                         buf[1] = buf[2];  
                         buf[2] = buf[3];  
                         nbytes = 3;  
          
                        return -1;  
                    }  
          
                    /* FORM XFree86 4.0.1 */  
                    *bp = buttons[(buf[0] & 0x07)];  
                    *dx = (buf[0] & 0x10) ? buf[1] - 256 : buf[1];  
                    *dy = (buf[0] & 0x20) ? -(buf[2] - 256) : -buf[2];  
          
                    /* Is a wheel event? */  
                    if ((wheel = buf[3]) != 0) {  
                        if(wheel > 0x7f) {  
                            *bp |= WHEEL_UP;  
                        }  
                        else {  
                            *bp |= WHEEL_DOWN;  
                        }  
                    }  
                       
                    *dz = 0;  
                     nbytes = 0;  
                    return 1;  
                }  
            }  
            return 0;  
        }  
          
        static int mouse_update(int dx, int dy, int dz)  
        {  
            int r;  
            int sign;  
              
             sign = 1;  
            if (dx < 0) {  
                 sign = -1;  
                 dx = -dx;  
            }  
            if (dx > thresh)  
                 dx = thresh + (dx - thresh) * scale;  
             dx *= sign;  
             xpos += dx;  
            if( xpos < minx )  
                 xpos = minx;  
            if( xpos > maxx )  
                 xpos = maxx;  
          
             sign = 1;  
            if (dy < 0) {  
                 sign = -1;  
                 dy = -dy;  
            }  
            if (dy > thresh)  
                 dy = thresh + (dy - thresh) * scale;  
             dy *= sign;  
             ypos += dy;  
            if ( ypos < miny )  
                 ypos = miny;  
            if ( ypos > maxy )  
                 ypos = maxy;  
          
            return 1;  
        }  
          
        static void mouse_setposition (int newx, int newy)  
        {  
            if (newx < minx)  
                 newx = minx;  
            if (newx > maxx)  
                 newx = maxx;  
            if (newy < miny)  
                 newy = miny;  
            if (newy > maxy)  
                 newy = maxy;  
            if (newx == xpos && newy == ypos)  
                return;  
             xpos = newx;  
             ypos = newy;  
        }  
          
        static void mouse_setrange (int newminx, int newminy, int newmaxx, int newmaxy)  
        {  
             minx = newminx;  
             miny = newminy;  
             maxx = newmaxx;  
             maxy = newmaxy;  
             mouse_setposition ((newminx + newmaxx) / 2, (newminy + newmaxy) / 2);  
        }  
          
        static int mouse_getbutton (void)  
        {  
            return buttons;  
        }  
          
        static void mouse_getxy (int* x, int* y)  
        {  
            *x = xpos;  
            *y = ypos;  
        }  
    

    用C语言在Linux下获取鼠标光标的相对位置代码分享:

        #include <stdio.h>   
        #include <stdlib.h>   
        #include <linux/input.h>   
        #include <fcntl.h>   
        #include <sys/time.h>   
        #include <sys/types.h>   
        #include <sys/stat.h>   
        #include <unistd.h>   
          
          
        int main(int argc,char **argv)  
        {  
            int fd, retval;  
            char buf[6];  
            fd_set readfds;  
            struct timeval tv;  
          
            //fd = open("/dev/input/mice", O_RDONLY);   
            if(( fd = open("/dev/input/mice", O_RDONLY))<0)  
            {  
                printf("Failed to open \"/dev/input/mice\".\n");  
                exit(1);  
            }  
            else  
            {  
                printf("open \"/dev/input/mice\" successfuly.\n");  
            }  
          
            while(1)  
            {  
                tv.tv_sec = 5;  
                tv.tv_usec = 0;  
          
                FD_ZERO(&readfds);  
                FD_SET(fd, &readfds);  
          
                retval = select(fd+1, &readfds, NULL, NULL, &tv);  
                if(retval==0)  
                printf("Time out!\n");  
                if(FD_ISSET(fd,&readfds))  
                {  
                    if(read(fd, buf, 6) <= 0)//终端设备,一次只能读取一行   
                    {  
                        continue;  
                    }  
                    printf("Button type = %d, X = %d, Y = %d, Z = %d\n", (buf[0] & 0x07), buf[1], buf[2],   buf[3]);  
                }  
            }  
            close(fd);  
            return 0;  
        }  
    

    A simple program to check the /dev/input/mouse0 datas

    Tested on the raspberry PI with GPM installed

    #include <stdio.h>
    #include <stdlib.h>
    #include <fcntl.h>
    #include <linux/input.h>
    
    #define MOUSEFILE "/dev/input/mouse0"
    //
    int main()
    {
        int fd;
        struct input_event ie;
        //
        unsigned char button,bLeft,bMiddle,bRight;
        char x,y;
        int absolute_x,absolute_y;
    
        if((fd = open(MOUSEFILE, O_RDONLY)) == -1) {
            printf("Device open ERROR\n");
            exit(EXIT_FAILURE);
        }
        else
        {
            printf("Device open OK\n");
        }
        //
        printf("right-click to set absolute x,y coordinates origin (0,0)\n");
        while(read(fd, &ie, sizeof(struct input_event)))
        {
            unsigned char *ptr = (unsigned char*)&ie;
            int i;       
            //
            button=ptr[0];
            bLeft = button & 0x1;
            bMiddle = ( button & 0x4 ) > 0;
            bRight = ( button & 0x2 ) > 0;
            x=(char) ptr[1];y=(char) ptr[2];
            printf("bLEFT:%d, bMIDDLE: %d, bRIGHT: %d, rx: %d  ry=%d\n",bLeft,bMiddle,bRight, x,y);
            //
            absolute_x+=x;
            absolute_y-=y;
            if (bRight==1)
            {
                absolute_x=0;
                absolute_y=0;
                printf("Absolute x,y coords origin recorded\n");
            }
            //
            printf("Absolute coords from TOP_LEFT= %i %i\n",absolute_x,absolute_y);
            //
            // comment to disable the display of raw event structure datas
            //
            for(i=0; i<sizeof(ie); i++)
            {
                printf("%02X ", *ptr++);
            }
            printf("\n");
        }
    
    return 0;
    }

    The read() command is blocking for now.
    The following C code does almost the same thing, with non-blocking option enabled this time:

    #include <stdio.h>
    #include <stdlib.h>
    #include <fcntl.h>
    #include <linux/input.h>
    
    #define MOUSEFILE "/dev/input/mouse0\0"
    //
    int main()
    {
        int fd;
        struct input_event ie;
        unsigned char *ptr = (unsigned char*)&ie;
        //
        unsigned char button,bLeft,bMiddle,bRight;
        char x,y;                                                            // the relX , relY datas
        int absolute_x,absolute_y;
    
        if((fd = open(MOUSEFILE, O_RDONLY | O_NONBLOCK )) == -1)
        {
            printf("NonBlocking %s open ERROR\n",MOUSEFILE);
            exit(EXIT_FAILURE);
        }
        else
        {
            printf("NonBlocking %s open OK\n",MOUSEFILE);
        }
        //
        printf("--------------------------------------------------------\n");
        printf("right-click to set absolute x,y coordinates origin (0,0)\n");
        printf("left+right click to EXIT\n");
        printf("--------------------------------------------------------\n");
        //
        while(1)
        {       
            if(read(fd, &ie, sizeof(struct input_event))!=-1)
            {
                //
                button=ptr[0];
                bLeft = button & 0x1;
                bMiddle = ( button & 0x4 ) > 0;
                bRight = ( button & 0x2 ) > 0;
                x=(char) ptr[1];y=(char) ptr[2];
                if(bLeft&bRight) { printf("\nright+left ,EXIT\n");break;}
                // computes absolute x,y coordinates
                absolute_x+=x;
                absolute_y-=y;
                // set absolute reference ?
                if (bRight==1)
                {
                    absolute_x=0;
                    absolute_y=0;
                    printf("Absolute x,y coords origin recorded\n");
                }
                // show it!
                printf("X%i Y%i\n",absolute_x,absolute_y);
                fflush(stdout);
            }
        }
        //
        close(fd);
    return 0;
    }
     

    除特别注明外,本站所有文章均为String me = "Creater\忠实的资深Linux玩家";原创,转载请注明出处来自http://unix8.net/home.php/4885.html

    关于

    发表评论

    暂无评论

    切换注册

    登录

    忘记密码 ?

    切换登录

    注册

    扫一扫二维码分享