This diff attempts to "unify" volume keys; it makes pckbd and ukbd
volume keys behave like all other volume keys (acpithinkpad,
acpiasus, macppc/abtn and similar drivers): simply adjust the
hardware volume without passing keystroke events to upper layers
(i.e. "consume" the keystroke).

If your volume keys tend to mess the volume while in X (example
mplayer), try this diff and see if it makes things better (or
worse).

--- sys/dev/pckbc/pckbd.c.orig  Tue Apr 29 19:29:09 2014
+++ sys/dev/pckbc/pckbd.c       Tue Apr 29 22:46:30 2014
@@ -177,7 +177,7 @@ int pckbd_init(struct pckbd_internal *, pckbc_tag_t, p
 void   pckbd_input(void *, int);
 
 static int     pckbd_decode(struct pckbd_internal *, int,
-                                 u_int *, int *);
+                                 u_int *, int *, int);
 static int     pckbd_led_encode(int);
 
 struct pckbd_internal pckbd_consdata;
@@ -788,7 +788,8 @@ pckbd_scancode_translate(struct pckbd_internal *id, in
 }
 
 static int
-pckbd_decode(struct pckbd_internal *id, int datain, u_int *type, int *dataout)
+pckbd_decode(struct pckbd_internal *id, int datain, u_int *type,
+    int *dataout, int raw)
 {
        int key;
        int releasing;
@@ -832,8 +833,8 @@ pckbd_decode(struct pckbd_internal *id, int datain, u_
                id->t_lastchar = 0;
                *type = WSCONS_EVENT_KEY_UP;
        } else {
-               /* Always ignore typematic keys */
-               if (key == id->t_lastchar)
+               /* Always ignore typematic keys, except in raw-mode */
+               if (key == id->t_lastchar && !raw)
                        return 0;
                id->t_lastchar = key;
                *type = WSCONS_EVENT_KEY_DOWN;
@@ -894,16 +895,25 @@ void
 pckbd_input(void *vsc, int data)
 {
        struct pckbd_softc *sc = vsc;
-       int rc, type, key;
+       int rc, type, key, consumed;
 
        data = pckbd_scancode_translate(sc->id, data);
        if (data == 0)
                return;
 
-       rc = pckbd_decode(sc->id, data, &type, &key);
+#ifdef WSDISPLAY_COMPAT_RAWKBD
+       rc = pckbd_decode(sc->id, data, &type, &key, sc->rawkbd);
+#else
+       rc = pckbd_decode(sc-id, data, &type, &key, 0);
+#endif
+       consumed = (rc != 0) ? wskbd_volkey(sc->sc_wskbddev, type, key) : 0;
 
 #ifdef WSDISPLAY_COMPAT_RAWKBD
        if (sc->rawkbd) {
+               if (consumed) {
+                       sc->sc_rawcnt = 0;
+                       return;
+               }
                sc->sc_rawbuf[sc->sc_rawcnt++] = (char)data;
 
                if (rc != 0 || sc->sc_rawcnt == sizeof(sc->sc_rawbuf)) {
@@ -911,15 +921,10 @@ pckbd_input(void *vsc, int data)
                            sc->sc_rawcnt);
                        sc->sc_rawcnt = 0;
                }
-
-               /*
-                * Pass audio keys to wskbd_input anyway.
-                */
-               if (rc == 0 || (key != 160 && key != 174 && key != 176))
-                       return;
+               return;
        }
 #endif
-       if (rc != 0)
+       if (rc != 0 && !consumed)
                wskbd_input(sc->sc_wskbddev, type, key);
 }
 
@@ -1024,7 +1029,7 @@ pckbd_cngetc(void *v, u_int *type, int *data)
                if (val == 0)
                        continue;
 
-               if (pckbd_decode(t, val, type, data))
+               if (pckbd_decode(t, val, type, data, 0))
                        return;
        }
 }
--- sys/dev/usb/hidkbd.c.orig   Tue Apr 29 19:29:09 2014
+++ sys/dev/usb/hidkbd.c        Tue Apr 29 19:29:24 2014
@@ -411,6 +411,9 @@ hidkbd_decode(struct hidkbd *kbd, struct hidkbd_data *
                for (i = j = 0; i < nkeys; i++) {
                        key = ibuf[i];
                        c = hidkbd_trtab[key & CODEMASK];
+                       if (wskbd_volkey(kbd->sc_wskbddev, (key & RELEASE) ?
+                               WSCONS_EVENT_KEY_UP : WSCONS_EVENT_KEY_DOWN, c))
+                               continue;
                        if (c == NN)
                                continue;
                        if (c & 0x80)
@@ -425,24 +428,7 @@ hidkbd_decode(struct hidkbd *kbd, struct hidkbd_data *
                }
                s = spltty();
                wskbd_rawinput(kbd->sc_wskbddev, cbuf, j);
-
-               /*
-                * Pass audio keys to wskbd_input anyway.
-                */
-               for (i = 0; i < nkeys; i++) {
-                       key = ibuf[i];
-                       switch (key & CODEMASK) {
-                       case 127:
-                       case 128:
-                       case 129:
-                               wskbd_input(kbd->sc_wskbddev,
-                                   key & RELEASE ?  WSCONS_EVENT_KEY_UP :
-                                     WSCONS_EVENT_KEY_DOWN, key & CODEMASK);
-                               break;
-                       }
-               }
                splx(s);
-
                return;
        }
 #endif
@@ -450,6 +436,10 @@ hidkbd_decode(struct hidkbd *kbd, struct hidkbd_data *
        s = spltty();
        for (i = 0; i < nkeys; i++) {
                key = ibuf[i];
+               if (wskbd_volkey(kbd->sc_wskbddev, (key & RELEASE) ?
+                       WSCONS_EVENT_KEY_UP : WSCONS_EVENT_KEY_DOWN,
+                       hidkbd_trtab[key & CODEMASK]))
+                       continue;
                wskbd_input(kbd->sc_wskbddev,
                    key&RELEASE ? WSCONS_EVENT_KEY_UP : WSCONS_EVENT_KEY_DOWN,
                    key&CODEMASK);
--- sys/dev/wscons/wskbd.c.orig Tue Apr 29 19:29:09 2014
+++ sys/dev/wscons/wskbd.c      Tue Apr 29 19:29:24 2014
@@ -698,6 +698,38 @@ wskbd_input(struct device *dev, u_int type, int value)
 }
 
 /*
+ * Check if the given key is a multimedia key to mute or
+ * increase/decrease speaker volume. If it is, then invoke the
+ * appropriate audio mixer bits and return 1 (means key is consumed),
+ * else return 0.
+ */
+int
+wskbd_volkey(struct device *dev, u_int type, int key)
+{
+       switch (key) {
+       case 160:
+#if NAUDIO > 0
+               if (type == WSCONS_EVENT_KEY_DOWN)
+                       wskbd_set_mixervolume(0, 1);
+#endif
+               return 1;
+       case 174:
+#if NAUDIO > 0
+               if (type == WSCONS_EVENT_KEY_DOWN)
+                       wskbd_set_mixervolume(-1, 1);
+#endif
+               return 1;
+       case 176:
+#if NAUDIO > 0
+               if (type == WSCONS_EVENT_KEY_DOWN)
+                       wskbd_set_mixervolume(1, 1);
+#endif
+               return 1;
+       }
+       return 0;
+}
+
+/*
  * Keyboard is generating events.  Turn this keystroke into an
  * event and put it in the queue.  If the queue is full, the
  * keystroke is lost (sorry!).
@@ -1677,25 +1709,6 @@ wskbd_translate(struct wskbd_internal *id, u_int type,
                } else {
                        gindex = MOD_ONESET(id, MOD_ANYSHIFT);
                        ksym = group[gindex];
-               }
-       }
-
-       /* Submit Audio keys for hotkey processing */
-       if (KS_GROUP(ksym) == KS_GROUP_Function) {
-               switch (ksym) {
-#if NAUDIO > 0
-               case KS_AudioMute:
-                       wskbd_set_mixervolume(0, 1);
-                       return (0);
-               case KS_AudioLower:
-                       wskbd_set_mixervolume(-1, 1);
-                       return (0);
-               case KS_AudioRaise:
-                       wskbd_set_mixervolume(1, 1);
-                       return (0);
-#endif
-               default:
-                       break;
                }
        }
 
--- sys/dev/wscons/wskbdvar.h.orig      Tue Apr 29 19:29:09 2014
+++ sys/dev/wscons/wskbdvar.h   Tue Apr 29 19:29:24 2014
@@ -91,6 +91,7 @@ int   wskbddevprint(void *, const char *);
  * Callbacks from the keyboard driver to the wskbd interface driver.
  */
 void   wskbd_input(struct device *kbddev, u_int type, int value);
+int    wskbd_volkey(struct device *kbddev, u_int type, int value);
 /* for WSDISPLAY_COMPAT_RAWKBD */
 void   wskbd_rawinput(struct device *, u_char *, int);
 

Reply via email to