You are not logged in.

#1 2009-02-18 09:12:38

lyndonwhaite
Member
Registered: 2009-02-18
Posts: 3

simple program to fix PS2 compatible mouse acceleration

I have only been using linux as my main OS for 6 months and i have mostly loved it, except for the absolutely horrid xorg mouse acceleration. The discontinuous acceleration curve in my opinion is really annoying and unusable.

In the linux spirit i wrote a simple program to improve it.

The program takes as arguments the PS2 compatible mouse device (eg /dev/mouse), a named pipe and the coefficients for a 3rd order polynomial. The program filters the mouse data according to the polynomial and writes the new data to the named pipe to be used by xorg.

If someone wants to try it

step 1.

turn off all other x mouse acceleration.

step 2.

gcc mouse.c -lm -o mousefilter

mkfifo fifo

step 3.

setup xorg.conf to use "fifo" as the mouse device

step 4.

run the program in startup script

eg

sudo mousefilter /dev/input/mice fifo 1 0.15 0

these arguments modulate the mouse coordinates with x + 0.15x^2 + 0*x.^3.
this is what i have been using all week and it works great.

I have only tested it on my current xubuntu system (I am about to install arch, when i get the time). So if it works
for you or doesn't i would be interested to hear.

/* mouse.c - PS2 mouse acceleration filter *****************************************************************
 * This program reads packets from a specfied PS/2 compatible mouse device, decodes them
 * scales the x and y movement according to a user specified polynomial, repacks
 * and writes to a fifo used as the mouse device. 
 * 
 * Author: Lyndon Whaite 2009
 *************************************************************************************************/ 

#include <fcntl.h>
#include <stdio.h>
#include <math.h>
#include <string.h>
#include <stdlib.h>

int fifo, mouse;
char is_4byte=0;
float poly_curve[] = {1,0,0};
  
/* evaluate user specified polynomial */
float evaluate_curve(float delta, float poly[])
{
    return poly[0]*delta + poly[1]*pow(delta,2) + poly[2]*pow(delta,3);
}

/* filter mouse data */
void filter_mouse(void)
{
  unsigned char in[4], out[4];
  int   xsign,ysign;
  float dx=0;
  float dy=0;
  float ndx=0;
  float ndy=0;
  float speed=0;
  float pspeed=0;
  float mouse_speed=0;
  float smooth_factor = 0.1;

  unsigned char mask = 1;

  while (1) 
  {  
    /* read 4th byte if it is an intellimouse */      
    if(is_4byte)
    {
       read(mouse,in,4);
    }
    else
    {
       read(mouse,in,3);
    }
    /* unpack mouse movement */
    xsign = (in[0]>>4)&mask;
    ysign = (in[0]>>5)&mask;

    dx=(in[1]-256*xsign);
    dy=(in[2]-256*ysign);

    mouse_speed = sqrt(dy*dy+dx*dx);
    speed = 0;
    ndx=0;
    ndy=0;
    
    /* evaluate scaling function if mouse is moving */
    if(mouse_speed > 0)
    {        
      ndx = (float)(dx)/mouse_speed;
      ndy = (float)(dy)/mouse_speed;
    
      pspeed = speed;
      speed = evaluate_curve(mouse_speed,poly_curve)*(1.0-smooth_factor*0.5)
                                  + (smooth_factor*0.5)*smooth_factor*pspeed;
    }
    
    /* put transformed data back in packets */
    dy = ndy*speed;
    dx = ndx*speed;
    
    out[0] = in[0];
    out[1] = floor(dx)+256*xsign;
    out[2] = floor(dy)+256*ysign;
    out[3] = in[3];

    /* write transformed packet to fifo */
    if(is_4byte)
    {
       write(fifo, out,4);
    }
    else
    {
       write(fifo, out,3);
    }
  }
}


int main(int argc, char **argv)
{
  int i=0;
  unsigned char temp_read=0;
  unsigned char imps23_seq[] = { 0xf3, 200, 0xf3, 100, 0xf3, 80 };
  unsigned char imps24_seq[] = { 0xf3, 200, 0xf3, 200, 0xf3, 80 };  
  unsigned char get_id = 0xf2;

  if (argc < 4) 
  {
    printf("usage: %s <mouse dev> <fifo> <poly coefficients (1-3 numbers)> <\n", argv[0]);
    exit(1);
  }
  
  /* open fifo file */
  fifo = open(argv[2], O_RDWR);
  
  if (fifo < 0) 
  {
    printf("error opening fifo\n");
    exit(1);
  }
  
   /* open mouse file */
  mouse = open(argv[1], O_RDWR);

  if (mouse < 0) 
  {
    printf("error opening mouse\n");
    close(fifo);
    exit(1);
  }
  
  for(i=0; i<argc-3; i++)
  {
    poly_curve[i] = atof(argv[i+3]);
  }
  
  printf("f(x) = %fx + %fx^2 + %fx^3\n", poly_curve[0],poly_curve[1], poly_curve[2]);
  
  /* initially assume normal ps/2 */
  is_4byte=0;
  
  /* write magic sequence */
  write(mouse,imps23_seq,6);

  write(mouse,&get_id,1);
  read(mouse, &temp_read, 1);
  read(mouse, &temp_read, 1);
  
  /* if device id == 3 it is a ps2 mouse with a wheel */
  if(temp_read==3)
  {
    printf("mouse has wheel\n");   
    is_4byte=1;
  }

  /* write magic sequence */ 
  write(mouse,imps24_seq,6);
  
  write(mouse,&get_id,1);
  read(mouse, &temp_read, 1);
  read(mouse, &temp_read, 1);
  
  /* if device id == 3 it is a ps2 mouse with a wheel and extra buttons*/
  if(temp_read==4)
  {
    printf("mouse has wheel and extra buttons\n");
    is_4byte=1;
  }
  
  /* try to set sample rate to 200 */
  write(mouse,imps23_seq,2);
  read(mouse, &temp_read, 1);
  
  /* infinite loop to filter mouse data */
  filter_mouse();

  close(fifo);
  close(mouse);
}

Lyndon

Last edited by lyndonwhaite (2009-02-18 22:55:40)

Offline

#2 2009-02-18 20:03:26

Heller_Barde
Member
Registered: 2008-04-01
Posts: 245

Re: simple program to fix PS2 compatible mouse acceleration

wow! cool, definitely gonna try that!
is my mouse with more than the standard buttons gonna work?

cheers Barde

Offline

#3 2009-02-18 20:11:30

Ashren
Member
From: Denmark
Registered: 2007-06-13
Posts: 1,229
Website

Re: simple program to fix PS2 compatible mouse acceleration

This is very cool eventhough I'm not even using a PS/2 mouse. I think you'll like Arch Linux.

Offline

#4 2009-02-18 22:54:22

lyndonwhaite
Member
Registered: 2009-02-18
Posts: 3

Re: simple program to fix PS2 compatible mouse acceleration

Thanks for the feedback guys.

Ashren wrote:

This is very cool eventhough I'm not even using a PS/2 mouse. I think you'll like Arch Linux.

Ashren it doesn't matter so much whether it is a PS2 mouse but whether it uses the PS2 protocol, yours might. I am using a USB intellimouse but it uses the PS2 protocol.

Heller_Barde wrote:

wow! cool, definitely gonna try that!
is my mouse with more than the standard buttons gonna work?

cheers Barde

I have got an MS Intellimouse with 5 buttons and that works. This is the reference i used for the mouse data. I think a lot of ps2 compatible mice with extra buttons use the intellimouse packet so it should work.

http://www.computer-engineering.org/ps2mouse/

I would like to extend the program to work with a reasonable subset of mice so let us know how it goes if you try it.

Lyndon

Offline

#5 2009-02-20 14:56:55

test1000
Member
Registered: 2005-04-03
Posts: 834

Re: simple program to fix PS2 compatible mouse acceleration

Is predictable pointer acc in new xserver going to fix this? (btw i have no idea what the issue is tongue) Because if not maybe you could help the xorg guys out instead and get it in tree(unless you will screw with my acc in fps's)!


KISS = "It can scarcely be denied that the supreme goal of all theory is to make the irreducible basic elements as simple and as few as possible without having to surrender the adequate representation of a single datum of experience." - Albert Einstein

Offline

#6 2009-02-21 04:46:26

lyndonwhaite
Member
Registered: 2009-02-18
Posts: 3

Re: simple program to fix PS2 compatible mouse acceleration

test1000 wrote:

Is predictable pointer acc in new xserver going to fix this? (btw i have no idea what the issue is tongue) Because if not maybe you could help the xorg guys out instead and get it in tree(unless you will screw with my acc in fps's)!

Yeah i am pretty sure they are intending to solve the problem in the next version of xserver, i am not sure when that is going to be out though. I needed a solution now smile

A lot of people don't seem to mind the standard mouse acceleration, i find it really annoying. The issue is basically that the standard mouse acceleration has only two speeds, the slow and the fast, the new xserver will have an infinite number of different speeds (ie a smooth nonlinear scaling function).

Offline

Board footer

Powered by FluxBB