NetBSD-Bugs archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
kern/46394: wsmouse - button remapping.
>Number: 46394
>Category: kern
>Synopsis: wsmouse - button remapping.
>Confidential: no
>Severity: serious
>Priority: high
>Responsible: kern-bug-people
>State: open
>Class: change-request
>Submitter-Id: net
>Arrival-Date: Tue May 01 14:45:00 +0000 2012
>Originator: Nat Sloss
>Release: NetBSD Current 6.99.5
>Organization:
>Environment:
NetBSD beast 6.99.5 NetBSD 6.99.5 (LOCKDEBUG) #41: Mon Apr 30 14:13:38 EST 2012
build@beast:/usr/src/sys/arch/i386/compile/obj/LOCKDEBUG i386
>Description:
Hi. Whilst playing around with button detection for my mouse and touchscreen I
noticed there was no way to remap the button functions if button 0 was not the
left most button and tip switch (for touchscreens and digitizers) was not
mapped to the left most button.
There is no provision in ws(4) to remap buttons and that's what I use for my
touchscreen. Luckily for me buttons are mapped properly, but if "tip" wasn't
button 0 I'd be stuck.
>How-To-Repeat:
Try using a mouse where by button 0 is not the left most button or a
touchscreen/digitizer where by the screen touch is not the tip switch but a tip
switch is detected.
You'll find you will have no way to change the button mappings.
>Fix:
Originally I had modified the xf86-input-ws driver so I could remap buttons,
but This only works in X. A system wide mechanism would be better.
So what I did was to add a button map array to the wsmouse struct and write a
function to remap the buttons and finally to add sysctl setup and verify
routines (Not the best way I believe, but the only way I knew how) to
facilitate button mapping changes.
I believe that changing button mappings would be better in wsconsctl but I have
no idea how to do it as yet, but I'm trying.
To use: sysctl -w hw.wsmouse.button0=-1 (to disable a button)
sysctl -w hw.wsmouse.button0=15 (To remap button 0 to 15)
I thought the ability to disable a button was important and its not even
available with xf86-input-mouse.
Button remapping/disabling can be done with xinput but in my opinion a system
wide one is better.
Note: This patch is my own work, which I make available under the NetBSD
license.
--- wsmouse.c.orig 2011-12-04 01:13:29.000000000 +1100
+++ wsmouse.c 2012-05-01 00:34:17.000000000 +1000
@@ -117,6 +117,7 @@
#include <sys/fcntl.h>
#include <sys/kernel.h>
#include <sys/proc.h>
+#include <sys/sysctl.h>
#include <sys/syslog.h>
#include <sys/systm.h>
#include <sys/tty.h>
@@ -144,6 +145,7 @@
#define INVALID_Y INT_MAX
#define INVALID_Z INT_MAX
#define INVALID_W INT_MAX
+#define NBUTTONS (int)(sizeof(u_int) * 8)
struct wsmouse_softc {
struct wsevsrc sc_base;
@@ -162,6 +164,10 @@
int sc_z; /* absolute-z */
int sc_w; /* absolute-w */
+ struct sysctllog *sc_log;
+ int sc_buttonMap[NBUTTONS]; /* button mappings */
+ int sc_buttonMib[NBUTTONS]; /* button sysctl nodes */
+
int sc_refcnt;
u_char sc_dying; /* device is being detached */
@@ -192,6 +198,8 @@
wsmouse_match, wsmouse_attach, wsmouse_detach, wsmouse_activate);
static void wsmouse_repeat(void *v);
+static void wsmouse_sysctl_setup(struct wsmouse_softc *);
+static int buttonRemap(struct wsmouse_softc *, int);
extern struct cfdriver wsmouse_cd;
@@ -237,6 +245,7 @@
{
struct wsmouse_softc *sc = device_private(self);
struct wsmousedev_attach_args *ap = aux;
+ int i;
#if NWSMUX > 0
int mux, error;
#endif
@@ -272,6 +281,12 @@
if (!pmf_device_register(self, NULL, NULL))
aprint_error_dev(self, "couldn't establish power handler\n");
+
+ /* Initialize button mappings 1:1 */
+ for (i = 0; i < NBUTTONS; i++)
+ sc->sc_buttonMap[i] = i;
+
+ wsmouse_sysctl_setup(sc);
}
int
@@ -336,9 +351,94 @@
mn = device_unit(self);
vdevgone(maj, mn, mn, VCHR);
+ if (sc->sc_log)
+ sysctl_teardown(&sc->sc_log);
+
return (0);
}
+static int
+button_sysctl_verify(SYSCTLFN_ARGS)
+{
+ struct sysctlnode node;
+ struct wsmouse_softc *sc;
+ int err, tmp, i;
+
+ node = *rnode;
+ sc = rnode->sysctl_data;
+
+ for (i = 0; i < NBUTTONS; i++) {
+ if (node.sysctl_num == sc->sc_buttonMib[i]) {
+ tmp = sc->sc_buttonMap[i];
+ node.sysctl_data = &tmp;
+
+ err = sysctl_lookup(SYSCTLFN_CALL(&node));
+ if (err || newp == NULL)
+ return err;
+
+ if (tmp < -1 || tmp > NBUTTONS - 1)
+ return EINVAL;
+
+ sc->sc_buttonMap[i] = tmp;
+ }
+ }
+
+ return 0;
+}
+
+static void
+wsmouse_sysctl_setup(struct wsmouse_softc *sc)
+{
+ const struct sysctlnode *node_button[NBUTTONS], *node;
+ int err, i;
+ char buttonName[SYSCTL_NAMELEN];
+
+ err = sysctl_createv(&sc->sc_log, 0, NULL, NULL, 0,
+ CTLTYPE_NODE, "hw", NULL, NULL, 0, NULL, 0, CTL_HW, CTL_EOL);
+ if (err)
+ goto sysctl_err;
+
+ err = sysctl_createv(&sc->sc_log, 0, NULL, &node, 0,
+ CTLTYPE_NODE, device_xname(sc->sc_base.me_dv),
+ SYSCTL_DESCR("wsmouse controls"), NULL, 0,
+ NULL, 0, CTL_HW, CTL_CREATE, CTL_EOL);
+ if (err)
+ goto sysctl_err;
+
+ for (i = 0; i < NBUTTONS; i++) {
+ snprintf(buttonName, sizeof(buttonName), "button%d", i);
+
+ err = sysctl_createv(&sc->sc_log, 0, &node,
+ &node_button[i], CTLFLAG_READWRITE|CTLFLAG_ANYWRITE,
+ CTLTYPE_INT, buttonName, SYSCTL_DESCR("button event
mapping"),
+ button_sysctl_verify, 0, sc, 0, CTL_CREATE, CTL_EOL);
+ if (err)
+ goto sysctl_err;
+ sc->sc_buttonMib[i] = node_button[i]->sysctl_num;
+ }
+
+ return;
+sysctl_err:
+ aprint_error_dev(sc->sc_base.me_dv, "failed to add sysctl nodes.
(%d)\n", err);
+}
+
+static int
+buttonRemap(struct wsmouse_softc *sc, int buttons)
+{
+ int buttonState, mappedButtons, i;
+
+ buttonState = buttons;
+ mappedButtons = 0;
+
+ for (i = 0; i < NBUTTONS; i++) {
+ if ((buttonState & 1) && (sc->sc_buttonMap[i] >= 0))
+ mappedButtons |= 1 << sc->sc_buttonMap[i];
+ buttonState >>= 1;
+ }
+
+ return mappedButtons;
+}
+
void
wsmouse_input(device_t wsmousedev, u_int btns /* 0 is up */,
int x, int y, int z, int w, u_int flags)
@@ -369,7 +469,7 @@
sc->sc_base.me_parent, evar));
#endif
- sc->sc_mb = btns;
+ sc->sc_mb = buttonRemap(sc, btns);
if (!(flags & WSMOUSE_INPUT_ABSOLUTE_X))
sc->sc_dx += x;
if (!(flags & WSMOUSE_INPUT_ABSOLUTE_Y))
Home |
Main Index |
Thread Index |
Old Index