> Hi,
> 
> last weekend, I noticed that after a
> 
> $ wsconsctl keyboard.map+="keysym Caps_Lock = Control_L"
> 
> on my PowerBook G4 the capslock key did *not* any longer behave
> like a control key. Instead it just has *no* effect at all, which
> isn't very surprising when looking at akbd_capslockwrapper() in
> akbd.c.
> 
> Isn't there any reliable way to detect *what* kind of keyboard is
> in use and then decide wether the hack in akbd_capslockwrapper()
> is necessary or not?

No. But what about this diff?

Miod

Index: akbd.c
===================================================================
RCS file: /cvs/src/sys/dev/adb/akbd.c,v
retrieving revision 1.4
diff -u -p -r1.4 akbd.c
--- akbd.c      2006/02/12 21:49:08     1.4
+++ akbd.c      2006/03/11 13:23:07
@@ -128,6 +128,7 @@ akbdattach(struct device *parent, struct
        sc->handler_id = aa_args->handler_id;
 
        sc->sc_leds = (u_int8_t)0x00;   /* initially off */
+       sc->sc_caps = 0;
 
        adbinfo.siServiceRtPtr = (Ptr)akbd_adbcomplete;
        adbinfo.siDataAreaAddr = (caddr_t)sc;
@@ -453,6 +454,30 @@ akbd_rawrepeat(void *v)
 #endif
 
 /*
+ * The ``caps lock'' key is special: since on earlier keyboards, the physical
+ * key stays down when pressed, we will get a notification of the key press,
+ * but not of the key release. Then, when it is pressed again, we will not get
+ * a notification of the key press, but will see the key release.
+ *
+ * This is not exactly true. We see the missing release and press events both
+ * as the release of the power (reset) key.
+ *
+ * To avoid confusing them with real power key presses, we maintain two
+ * states for the caps lock key: logically down (from wscons' point of view),
+ * and ``physically'' down (from the adb messages point of view), to ignore
+ * the power key. But since one may press the power key while the caps lock
+ * is held down, we also have to remember the state of the power key... this
+ * is quite messy.
+ */
+
+/*
+ * Values for caps lock state machine
+ */
+#define        CL_DOWN_ADB     0x01
+#define        CL_DOWN_LOGICAL 0x02
+#define        CL_DOWN_RESET   0x04
+
+/*
  * Given a keyboard ADB event, decode the keycodes and pass them to wskbd.
  */
 void
@@ -468,10 +493,24 @@ akbd_processevent(struct akbd_softc *sc,
                 * 0xffff on release, and we ignore it.
                 */
                if (event->bytes[0] == event->bytes[1] &&
-                   ADBK_KEYVAL(event->bytes[0]) == ADBK_RESET)
-                       break;
-               akbd_capslockwrapper(sc, event->bytes[0]);
-               akbd_capslockwrapper(sc, event->bytes[1]);
+                   ADBK_KEYVAL(event->bytes[0]) == ADBK_RESET) {
+                       if (event->bytes[0] == ADBK_KEYDOWN(ADBK_RESET))
+                               SET(sc->sc_caps, CL_DOWN_RESET);
+                       else {
+                               if (ISSET(sc->sc_caps, CL_DOWN_RESET))
+                                       CLR(sc->sc_caps, CL_DOWN_RESET);
+                               else if (ISSET(sc->sc_caps, CL_DOWN_ADB)) {
+                                       akbd_input(sc, ISSET(sc->sc_caps,
+                                           CL_DOWN_LOGICAL) ?
+                                             ADBK_KEYDOWN(ADBK_CAPSLOCK) :
+                                             ADBK_KEYUP(ADBK_CAPSLOCK));
+                                       sc->sc_caps ^= CL_DOWN_LOGICAL;
+                               }
+                       }
+               } else {
+                       akbd_capslockwrapper(sc, event->bytes[0]);
+                       akbd_capslockwrapper(sc, event->bytes[1]);
+               }
                break;
        default:
 #ifdef DIAGNOSTIC
@@ -486,22 +525,11 @@ akbd_processevent(struct akbd_softc *sc,
 void
 akbd_capslockwrapper(struct akbd_softc *sc, int key)
 {
-       /*
-        * Caps lock is special: since on earlier keyboards, the physical
-        * key stays down when pressed, we will get a notification of the
-        * key press, but not of the key release. Then, when it is pressed
-        * again, we will not get a notification of the key press, but will
-        * see the key release.
-        * For proper wskbd operation, we should report each capslock
-        * notification as both events (press and release).
-        */
-       if (ADBK_KEYVAL(key) == ADBK_CAPSLOCK) {
-               akbd_input(sc, ADBK_KEYDOWN(ADBK_CAPSLOCK));
-               akbd_input(sc, ADBK_KEYUP(ADBK_CAPSLOCK));
-       } else {
-               if (key != 0xff)
-                       akbd_input(sc, key);
-       }
+       if (ADBK_KEYVAL(key) == ADBK_CAPSLOCK)
+               sc->sc_caps ^= CL_DOWN_ADB;
+
+       if (key != 0xff)
+               akbd_input(sc, key);
 }
 
 int adb_polledkey;
Index: akbdvar.h
===================================================================
RCS file: /cvs/src/sys/dev/adb/akbdvar.h,v
retrieving revision 1.1
diff -u -p -r1.1 akbdvar.h
--- akbdvar.h   2006/01/18 23:21:17     1.1
+++ akbdvar.h   2006/03/11 13:23:07
@@ -46,7 +46,10 @@ struct akbd_softc {
        int             handler_id;     /* type of keyboard */
 
        u_int8_t        sc_leds;        /* current LED state */
+
+       int             sc_caps;        /* capslock key state */
        struct device   *sc_wskbddev;
+
 #ifdef WSDISPLAY_COMPAT_RAWKBD
 #define MAXKEYS 20
 #define REP_DELAY1 400

Reply via email to