tech-kern archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

Adding mouse sensitivity adjustment to wsmouse



Hi,

I would like to adjust the sensitivity of my external mouse but leave the 
sensitivity of my laptop touchpad as is. As far as I can tell, NetBSD has no 
facility to do this. I found a couple of mouse ioctl definitions (but no 
implementations) that seem relevant and also kern/12132 that partially 
implements what I need. I propose changing wsmouse.c as indicated in the 
attached diff. It adds scaling factors for x, y, z, and w into the 
wsmouse_softc structure and uses a higher resolution internally in order to 
handle fractions without adding floats.

WSCONS_MOUSE_RES is (the inverse of) the internal resolution and
sc_mx, sc_my, etc are the scaling factors (multiplied with WSCONS_MOUSE_RES).

It appears to work for my case with a regular bluetooth mouse but it has not 
been tested for a device producing absolute positions.

If this looks OK, we need to decide how to set the scaling factors. There are 
two ioctls that appear relevant (from wsconsio.h):

/* Set resolution.  Not applicable to all mouse types. */
#define WSMOUSEIO_SRES          _IOW('W', 33, u_int)
#define WSMOUSE_RES_MIN         0
#define WSMOUSE_RES_DEFAULT     75
#define WSMOUSE_RES_MAX         100

/* Set scale factor (num / den).  Not applicable to all mouse types. */
#define WSMOUSEIO_SSCALE        _IOW('W', 34, u_int[2])

WSMOUSEIO_SRES has been implemented for one driver 
(sys/arch/hpcmips/vr/vrpiu.c) but I'm not sure what is does. WSMOUSEIO_SSCALE 
has not been implemented for any driver (but see kern/12132). My current test 
implementaion ignores WSMOUSEIO_SRES and changes WSMOUSEIO_SSCALE to take a 
single integer which is used to set the x and y scaling factors. Because 
WSMOUSE_RES_MAX is 100, the WSMOUSEIO_SSCALE value can be described as a 
percent scaling. This is sufficient for my needs but we might want to scale x 
and y differently and also set scaling factors for z and w.

If there is interest and we can reach a consensus on the ioctl question I can 
clean this up and submit it. Please let me know.

Regards,
Sverre

Index: sys/dev/wscons/wsmouse.c
===================================================================
RCS file: /cvsroot/src/sys/dev/wscons/wsmouse.c,v
retrieving revision 1.62
diff -u -p -r1.62 wsmouse.c
--- sys/dev/wscons/wsmouse.c    15 Jan 2009 04:22:11 -0000      1.62
+++ sys/dev/wscons/wsmouse.c    18 May 2010 20:39:35 -0000
@@ -144,6 +144,8 @@ extern int wsmuxdebug;
 #define INVALID_Y      INT_MAX
 #define INVALID_Z      INT_MAX
 
+#define WSCONS_MOUSE_RES       100
+
 struct wsmouse_softc {
        struct wsevsrc  sc_base;
 
@@ -161,6 +163,11 @@ struct wsmouse_softc {
        int             sc_z;           /* absolute-z */
        int             sc_w;           /* absolute-w */
 
+       u_int           sc_mx;
+       u_int           sc_my;
+       u_int           sc_mz;
+       u_int           sc_mw;
+
        int             sc_refcnt;
        u_char          sc_dying;       /* device is being detached */
 
@@ -251,6 +258,12 @@ wsmouse_attach(device_t parent, device_t
        callout_init(&sc->sc_repeat_callout, 0);
        callout_setfunc(&sc->sc_repeat_callout, wsmouse_repeat, sc);
 
+       /* One-to-one scale multipliers. */
+       sc->sc_mx = WSCONS_MOUSE_RES;
+       sc->sc_my = WSCONS_MOUSE_RES;
+       sc->sc_mz = WSCONS_MOUSE_RES;
+       sc->sc_mw = WSCONS_MOUSE_RES;
+
 #if NWSMUX > 0
        sc->sc_base.me_ops = &wsmouse_srcops;
        mux = device_cfdata(self)->wsmousedevcf_mux;
@@ -368,6 +381,11 @@ wsmouse_input(device_t wsmousedev, u_int
                    sc->sc_base.me_parent, evar));
 #endif
 
+       x *= sc->sc_mx;
+       y *= sc->sc_my;
+       z *= sc->sc_mz;
+       w *= sc->sc_mw;
+
        sc->sc_mb = btns;
        if (!(flags & WSMOUSE_INPUT_ABSOLUTE_X))
                sc->sc_dx += x;
@@ -389,54 +407,54 @@ wsmouse_input(device_t wsmousedev, u_int
        nevents = 0;
 
        if (flags & WSMOUSE_INPUT_ABSOLUTE_X) {
-               if (sc->sc_x != x) {
+               if ((sc->sc_x - x) / WSCONS_MOUSE_RES) {
                        events[nevents].type = WSCONS_EVENT_MOUSE_ABSOLUTE_X;
-                       events[nevents].value = x;
+                       events[nevents].value = x / WSCONS_MOUSE_RES;
                        nevents++;
                }
        } else {
-               if (sc->sc_dx) {
+               if (sc->sc_dx / WSCONS_MOUSE_RES) {
                        events[nevents].type = WSCONS_EVENT_MOUSE_DELTA_X;
-                       events[nevents].value = sc->sc_dx;
+                       events[nevents].value = sc->sc_dx / WSCONS_MOUSE_RES;
                        nevents++;
                }
        }
        if (flags & WSMOUSE_INPUT_ABSOLUTE_Y) {
-               if (sc->sc_y != y) {
+               if ((sc->sc_y - y) / WSCONS_MOUSE_RES) {
                        events[nevents].type = WSCONS_EVENT_MOUSE_ABSOLUTE_Y;
-                       events[nevents].value = y;
+                       events[nevents].value = y / WSCONS_MOUSE_RES;
                        nevents++;
                }
        } else {
-               if (sc->sc_dy) {
+               if (sc->sc_dy / WSCONS_MOUSE_RES) {
                        events[nevents].type = WSCONS_EVENT_MOUSE_DELTA_Y;
-                       events[nevents].value = sc->sc_dy;
+                       events[nevents].value = sc->sc_dy / WSCONS_MOUSE_RES;
                        nevents++;
                }
        }
        if (flags & WSMOUSE_INPUT_ABSOLUTE_Z) {
-               if (sc->sc_z != z) {
+               if ((sc->sc_z - z) / WSCONS_MOUSE_RES) {
                        events[nevents].type = WSCONS_EVENT_MOUSE_ABSOLUTE_Z;
-                       events[nevents].value = z;
+                       events[nevents].value = z / WSCONS_MOUSE_RES;
                        nevents++;
                }
        } else {
-               if (sc->sc_dz) {
+               if (sc->sc_dz / WSCONS_MOUSE_RES) {
                        events[nevents].type = WSCONS_EVENT_MOUSE_DELTA_Z;
-                       events[nevents].value = sc->sc_dz;
+                       events[nevents].value = sc->sc_dz / WSCONS_MOUSE_RES;
                        nevents++;
                }
        }
        if (flags & WSMOUSE_INPUT_ABSOLUTE_W) {
-               if (sc->sc_w != w) {
+               if ((sc->sc_w - w) / WSCONS_MOUSE_RES) {
                        events[nevents].type = WSCONS_EVENT_MOUSE_ABSOLUTE_W;
-                       events[nevents].value = w;
+                       events[nevents].value = w / WSCONS_MOUSE_RES;
                        nevents++;
                }
        } else {
-               if (sc->sc_dw) {
+               if (sc->sc_dw / WSCONS_MOUSE_RES) {
                        events[nevents].type = WSCONS_EVENT_MOUSE_DELTA_W;
-                       events[nevents].value = sc->sc_dw;
+                       events[nevents].value = sc->sc_dw / WSCONS_MOUSE_RES;
                        nevents++;
                }
        }
@@ -494,10 +512,10 @@ wsmouse_input(device_t wsmousedev, u_int
                /* All events were correctly injected into the queue.
                 * Synchronize the mouse's status with what the user
                 * has received. */
-               sc->sc_x = x; sc->sc_dx = 0;
-               sc->sc_y = y; sc->sc_dy = 0;
-               sc->sc_z = z; sc->sc_dz = 0;
-               sc->sc_w = w; sc->sc_dw = 0;
+               sc->sc_x = x; sc->sc_dx %= WSCONS_MOUSE_RES;
+               sc->sc_y = y; sc->sc_dy %= WSCONS_MOUSE_RES;
+               sc->sc_z = z; sc->sc_dz %= WSCONS_MOUSE_RES;
+               sc->sc_w = w; sc->sc_dw %= WSCONS_MOUSE_RES;
                sc->sc_ub = ub;
 #if NWSMUX > 0
                DPRINTFN(5,("wsmouse_input: %s wakeup evar=%p\n",


Home | Main Index | Thread Index | Old Index