Subject: kern/25977: Implement WSMOUSEIO_SSCALE as software scaling
To: None <gnats-bugs@gnats.NetBSD.org>
From: Paul Ripke <stix@stix-amd.stix.org.au>
List: netbsd-bugs
Date: 06/20/2004 14:30:49
>Number: 25977
>Category: kern
>Synopsis: Implement WSMOUSEIO_SSCALE as software scaling
>Confidential: no
>Severity: non-critical
>Priority: low
>Responsible: kern-bug-people
>State: open
>Class: change-request
>Submitter-Id: net
>Arrival-Date: Sun Jun 20 04:58:00 UTC 2004
>Closed-Date:
>Last-Modified:
>Originator: Paul Ripke
>Release: NetBSD 2.0_BETA
>Organization:
>Environment:
System: NetBSD stix-amd.stix.org.au 2.0_BETA NetBSD 2.0_BETA (STIX-AMD) #5: Sun Jun 20 13:57:36 EST 2004 stix@stix-amd.stix.org.au:/export/build/netbsd-2-0/obj.i386/export/build/netbsd-2-0/src/sys/arch/i386/compile/STIX-AMD i386
Architecture: i386
Machine: i386
>Description:
I have a USB mouse with an annoying feature - the smallest delta the mouse
returns is 4 in either the x or y axis. No matter what settings are used
in X, jumpy behaviour results. Seeing WSMOUSEIO_SSCALE in the kernel
source, I implemented it as generic software scaling in the wscons layer.
I've run the following patch on i386 for some time with no problems.
>How-To-Repeat:
>Fix:
Index: sbin/wsconsctl/mouse.c
===================================================================
RCS file: /cvsroot/src/sbin/wsconsctl/mouse.c,v
retrieving revision 1.3
diff -u -d -b -w -r1.3 mouse.c
--- sbin/wsconsctl/mouse.c 15 Nov 1999 13:47:30 -0000 1.3
+++ sbin/wsconsctl/mouse.c 20 Jun 2004 03:59:22 -0000
@@ -45,10 +45,12 @@
static int mstype;
static int resolution;
static int samplerate;
+static int scaling[2];
struct field mouse_field_tab[] = {
{ "resolution", &resolution, FMT_UINT, FLG_WRONLY },
{ "samplerate", &samplerate, FMT_UINT, FLG_WRONLY },
+ { "scaling", &scaling, FMT_SCALE, FLG_WRONLY },
{ "type", &mstype, FMT_MSTYPE, FLG_RDONLY },
};
@@ -69,6 +71,7 @@
int fd;
{
int tmp;
+ int scale[2];
if (field_by_value(&resolution)->flags & FLG_SET) {
tmp = resolution;
@@ -79,7 +82,14 @@
if (field_by_value(&samplerate)->flags & FLG_SET) {
tmp = samplerate;
if (ioctl(fd, WSMOUSEIO_SRATE, &tmp) < 0)
- err(1, "WSMOUSEIO_SRES");
+ err(1, "WSMOUSEIO_SRATE");
pr_field(field_by_value(&tmp), " -> ");
}
+ if (field_by_value(&scaling)->flags & FLG_SET) {
+ scale[0] = scaling[0];
+ scale[1] = scaling[1];
+ if (ioctl(fd, WSMOUSEIO_SSCALE, &scale) < 0)
+ err(1, "WSMOUSEIO_SSCALE");
+ pr_field(field_by_value(&scaling), " -> ");
+ }
}
Index: sbin/wsconsctl/util.c
===================================================================
RCS file: /cvsroot/src/sbin/wsconsctl/util.c,v
retrieving revision 1.17
diff -u -d -b -w -r1.17 util.c
--- sbin/wsconsctl/util.c 21 Jan 2004 15:39:34 -0000 1.17
+++ sbin/wsconsctl/util.c 20 Jun 2004 03:59:22 -0000
@@ -226,6 +226,10 @@
case FMT_UINT:
printf("%u", *((u_int *) f->valp));
break;
+ case FMT_SCALE:
+ printf("%d/%d", ((u_int *) f->valp)[0],
+ ((int *) f->valp)[1]);
+ break;
case FMT_STRING:
printf("\"%s\"", *((char **) f->valp));
break;
@@ -289,6 +293,18 @@
else
*((u_int *) f->valp) = u;
break;
+ case FMT_SCALE:
+ p = strchr(val, '/');
+ if (p == NULL)
+ errx(1, "%s: not a valid scaling", val);
+ *p++ = '\0';
+ if (sscanf(val, "%d", &i) != 1)
+ errx(1, "%s: not a number", val);
+ ((int *) f->valp)[0] = i;
+ if (sscanf(p, "%d", &i) != 1)
+ errx(1, "%s: not a number", p);
+ ((int *) f->valp)[1] = i;
+ break;
case FMT_STRING:
if ((*((char **) f->valp) = strdup(val)) == NULL)
err(1, "strdup");
Index: sbin/wsconsctl/wsconsctl.h
===================================================================
RCS file: /cvsroot/src/sbin/wsconsctl/wsconsctl.h,v
retrieving revision 1.3
diff -u -d -b -w -r1.3 wsconsctl.h
--- sbin/wsconsctl/wsconsctl.h 7 Apr 2002 10:40:04 -0000 1.3
+++ sbin/wsconsctl/wsconsctl.h 20 Jun 2004 03:59:22 -0000
@@ -43,6 +43,7 @@
void *valp;
#define FMT_UINT 1 /* unsigned integer */
#define FMT_STRING 2 /* zero terminated string */
+#define FMT_SCALE 3 /* scaling in form 'num/den' */
#define FMT_KBDTYPE 101 /* keyboard type */
#define FMT_MSTYPE 102 /* mouse type */
#define FMT_DPYTYPE 103 /* display type */
Index: sys/dev/wscons/wsconsio.h
===================================================================
RCS file: /cvsroot/src/sys/dev/wscons/wsconsio.h,v
retrieving revision 1.61.2.3
diff -u -d -b -w -r1.61.2.3 wsconsio.h
--- sys/dev/wscons/wsconsio.h 7 Jun 2004 09:54:21 -0000 1.61.2.3
+++ sys/dev/wscons/wsconsio.h 20 Jun 2004 03:59:23 -0000
@@ -200,8 +200,8 @@
#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])
+/* Set software scale factor (num / den). */
+#define WSMOUSEIO_SSCALE _IOW('W', 34, int[2])
/* Set sample rate. Not applicable to all mouse types. */
#define WSMOUSEIO_SRATE _IOW('W', 35, u_int)
Index: sys/dev/wscons/wsmouse.c
===================================================================
RCS file: /cvsroot/src/sys/dev/wscons/wsmouse.c,v
retrieving revision 1.34
diff -u -d -b -w -r1.34 wsmouse.c
--- sys/dev/wscons/wsmouse.c 28 Nov 2003 13:19:46 -0000 1.34
+++ sys/dev/wscons/wsmouse.c 20 Jun 2004 03:59:24 -0000
@@ -129,6 +129,8 @@
int sc_refcnt;
u_char sc_dying; /* device is being detached */
+ int sc_scale_num; /* x/y delta scaling numerator */
+ int sc_scale_den; /* x/y delta scaling denominator */
};
static int wsmouse_match(struct device *, struct cfdata *, void *);
@@ -201,6 +203,8 @@
sc->sc_accessops = ap->accessops;
sc->sc_accesscookie = ap->accesscookie;
+ sc->sc_scale_num = 1;
+ sc->sc_scale_den = 1;
#if NWSMUX > 0
sc->sc_base.me_ops = &wsmouse_srcops;
@@ -311,9 +315,9 @@
sc->sc_mb = btns;
if (!(flags & WSMOUSE_INPUT_ABSOLUTE_X))
- sc->sc_dx += x;
+ sc->sc_dx += x * sc->sc_scale_num / sc->sc_scale_den;
if (!(flags & WSMOUSE_INPUT_ABSOLUTE_Y))
- sc->sc_dy += y;
+ sc->sc_dy += y * sc->sc_scale_num / sc->sc_scale_den;
if (!(flags & WSMOUSE_INPUT_ABSOLUTE_Z))
sc->sc_dz += z;
@@ -595,6 +599,12 @@
if (*(int *)data != sc->sc_base.me_evp->io->p_pgid)
return (EPERM);
return (0);
+ case WSMOUSEIO_SSCALE:
+ if (((int *)data)[0] == 0 || ((int *)data)[1] == 0)
+ return EINVAL;
+ sc->sc_scale_num = ((int *)data)[0];
+ sc->sc_scale_den = ((int *)data)[1];
+ return (0);
}
/*
>Release-Note:
>Audit-Trail:
>Unformatted: