Subject: Re: Anyone got a type-4 keyboard?
To: NetBSD port-sparc mailing list <port-sparc@netbsd.org>
From: Greg A. Woods <woods@weird.com>
List: port-sparc
Date: 10/08/2002 22:48:52
[ On Tuesday, October 8, 2002 at 19:23:30 (+0100), Julian Coleman wrote: ]
> Subject: Re: Anyone got a type-4 keyboard?
>
> Running vi under 1.5 on the console of a 4/330 with a type 4 keyboard, the
> keypad keys don't work (never noticed before - I always use 'h', 'j', 'k'
> and 'l' ;-).  Adding the following as ~/.termcap and setting $TERM to
> "sun-type4" fixes that :
> 
>   sun-type4:\
>   	:kd=\E[221z:kl=\E[217z:kr=\E[219z:ku=\E[215z:tc=sun-il:
> 
> It also makes the cursor keys work with `set -E` in /bin/sh.

Hmmm... that made me think about something I'd seen a while ago, and
since I had come to a clean juncture where shutting down my desktop
wouldn't matter I logged out and sure enough the keypad cursor keys
generate the above sequences on this SS20 with type-4 keyboard!

This confused me enormously since I'm pretty sure that's not what
happens under SunOS-5, and indeed on all versions of SunOS-5 that I've
looked on the headless machines I now have access to at you'll find that
both their termcap file, and the default terminfo files, for both 'sun'
and 'sun1' say:

	ku=\E[A:kd=\E[B:kr=\E[C:kl=\E[D

and

	kcub1=\E[D, kcud1=\E[B, kcuf1=\E[C, kcuu1=\E[A,

respectively.

I also noted that in NetBSD's sys/dev/sun/kbd_tables.c there are special
string definitions for the arrow and home keys which suggest the driver
should be translating those keys into the "standard" ANSI X3.64
sequences as defined in our own termcap.src too.


There is some confusion though because the kb(7m) manual page for the
console keyboard driver STREAMS module says:

     In TR_ASCII mode, when a function key is pressed,  the  fol-
     lowing escape sequence is sent:
          ESC[0....9z
     where ESC is a single escape character and "0...9" indicates
     the  decimal  representation of the function-key value.  For
     example, function key R1 sends the sequence:
          ESC[208z
     because the decimal value of  RF(1)  is  208.

Later it says:

     FUNCKEYS 0x600      Function  keys.   The  next-to-lowest  4
                         bits  indicate  the  group  of  function
                         keys:

                              LEFTFUNC 0x600
                              RIGHTFUNC 0x610
                              TOPFUNC 0x620
                              BOTTOMFUNC 0x630

     The low 4 bits indicate the function key number  within  the
     group:

          LF(n)               (LEFTFUNC+(n)-1)
          RF(n)               (RIGHTFUNC+(n)-1)
          TF(n)               (TOPFUNC+(n)-1)
          BF(n)               (BOTTOMFUNC+(n)-1)

and according to keytables(4), which gives the default standard
translation table for a U.S. Type 4 keyboard:

          key 21     all rf(1)
          key 22     all rf(2)
          key 23     all rf(3)
          key 45     all rf(4) numl padequal
          key 46     all rf(5) numl padslash
          key 47     all rf(6) numl padstar
          key 50     all bf(10) numl padequal
          key 68     all rf(7) numl pad7
          key 69     all rf(8) numl pad8
          key 70     all rf(9) numl pad9
          key 71     all bf(15) numl padminus
          key 90     all bf(11) numl padenter
          key 91     all rf(10) numl pad4
          key 92     all rf(11) numl pad5
          key 93     all rf(12) numl pad6
          key 94     all bf(8) numl pad0
          key 112    all rf(13) numl pad1
          key 113    all rf(14) numl pad2
          key 114    all rf(15) numl pad3
          key 125    all bf(14) numl padplus


Now here's where it gets a wee bit confusing.  kb(7m) also says:

     STRING 0x500        The low-order  bits  index  a  table  of
                         strings.  When a key with a STRING entry
                         is  depressed,  the  characters  in  the
                         null-terminated  string for that key are
                         sent, character by character.  The  max-
                         imum length is defined as:

                              KTAB_STRLEN 10

                         Individual string  numbers  are  defined
                         as:

                              HOMEARROW      0x00
                              UPARROW        0x01
                              DOWNARROW      0x02
                              LEFTARROW      0x03
                              RIGHTARROW     0x04

                         String numbers 0x05 - 0x0F are available
                         for custom entries.

and keytables(4) says keys can be mapped using these expressions:

             string+uparrow
                  the key is to be the "up arrow" key

             string+downarrow
                  the key is to be the "down arrow" key

             string+leftarrow
                  the key is to be the "left arrow" key

             string+rightarrow
                  the key is to be the "right arrow" key

             string+homearrow
                  the key is to be the "home" key


However in the default mapping table for the US type-4 as given in the
manual page none of the above expressions are used.

Of course that's still not the full story (this is Solaris, after all!).

According to loadkeys(1):

     By     default,      loadkeys      loads      the      file:
     /usr/share/lib/keytables/type_tt/layout_dd,  where tt is the
     value returned by the KIOCTYPE ioctl, and dd  is  the  value
     returned  by  the  KIOCLAYOUT  ioctl (see kb(7M)).  On self-
     identifying keyboards, the value returned by the  KIOCLAYOUT
     ioctl is set from the DIP switches. These files specify only
     the entries that change between the  different  Type-4  key-
     board layouts.

and 'loadkeys is indeed run on boot by /etc/rcS.d/S33keymap.sh (with an
undocumented '-e' on SunOS-5.6).

Interestingly type_4/us is one of the few translation tables that indeed
does not define any keys with the 'string+' expressions.  Only these
matching 'us*' do:

$ fgrep string /usr/share/lib/keytables/type_4/us*     
/usr/share/lib/keytables/type_4/us101a_pc:key 20   all string+uparrow
/usr/share/lib/keytables/type_4/us101a_pc:key 24   all string+leftarrow
/usr/share/lib/keytables/type_4/us101a_pc:key 27   all string+downarrow
/usr/share/lib/keytables/type_4/us101a_pc:key 28   all string+rightarrow
/usr/share/lib/keytables/type_4/us_5:key 20   all string+uparrow
/usr/share/lib/keytables/type_4/us_5:key 24   all string+leftarrow
/usr/share/lib/keytables/type_4/us_5:key 27   all string+downarrow
/usr/share/lib/keytables/type_4/us_5:key 28   all string+rightarrow
/usr/share/lib/keytables/type_4/us_hobo:key 20   all string+uparrow
/usr/share/lib/keytables/type_4/us_hobo:key 24   all string+leftarrow
/usr/share/lib/keytables/type_4/us_hobo:key 27   all string+downarrow
/usr/share/lib/keytables/type_4/us_hobo:key 28   all string+rightarrow

and those are all type-5 key codes despite the directory name, though
there is a note in kb(7m)

     Many of the keyboards released after  Sun  Type  4  keyboard
     also report themselves  as Sun Type 4 keyboard.

Yuck.


Now back to NetBSD.

In sys/dev/sun/kbd_tables.h we see:

	/*
	 * The string entry class.
	 * The low 4 bits select one of the entries from
	 * the string table.  (see kbd_stringtab[])
	 * By default, the string table has ANSI movement
	 * sequences for the arrow keys.
	 */
	#define KEYSYM_STRING 0x0500

and in sys/dev/sun/kbd_tables.c we see:


	/*
	 * Strings indexed by:  (KEYSYM_STRING | idx)
	 */
	char kbd_stringtab[16][10] = {
	        { 0x1b, '[', 'H', 0 },  /* 0: Home */
	        { 0x1b, '[', 'A', 0 },  /* 1: Up   */
	        { 0x1b, '[', 'B', 0 },  /* 2: Down */
	        { 0x1b, '[', 'D', 0 },  /* 3: Left */
	        { 0x1b, '[', 'C', 0 },  /* 4: Right */
	};

and still in sys/dev/sun/kbd_tables.c we also see:

	/*
	 * Keymaps for the "type 4" keyboard.
	 * (lower-case, upper-case)
	 */
	
	u_short keymap_s4_lc[KEYMAP_SIZE] = {

(it's the same in keymap_s4_uc too)

	    /*  24: T5_Left     */      KEYSYM_STRING | 3,

	    /*  20: T5_Up       */      KEYSYM_STRING | 1,

	    /*  27: T5_Down     */      KEYSYM_STRING | 2,
	    /*  28: T5_Right    */      KEYSYM_STRING | 4,

	    /*  52: T5_Home     */      KEYSYM_FUNC_R(7),


but for the type-4 keypad we only have:

	    /*  68: R7/Home     */      KEYSYM_FUNC_R(7),
	    /*  69: R8/Up       */      KEYSYM_FUNC_R(8),
	    /*  70: R9/PgUp     */      KEYSYM_FUNC_R(9),
	    /*  71: KP_Minus    */      KEYSYM_FUNC_N(15),

	    /*  90: KP_Enter    */      KEYSYM_FUNC_N(11),
	    /*  91: R10/Left    */      KEYSYM_FUNC_R(10),
	    /*  92: R11/KP_5    */      KEYSYM_FUNC_R(11),
	    /*  93: R12/Right   */      KEYSYM_FUNC_R(12),
	    /*  94: KP_Insert   */      KEYSYM_FUNC_N(8),

	    /*  96: T5_PgUp     */      KEYSYM_FUNC_R(9),

	    /* 112: R13/End     */      KEYSYM_FUNC_R(13),
	    /* 113: R14/Down    */      KEYSYM_FUNC_R(14),
	    /* 114: R15/PgDn    */      KEYSYM_FUNC_R(15),


In the CVS history for sys/dev/sun/kbd_tables.c we find:

	----------------------------
	revision 1.7
	date: 2002/04/12 14:27:29;  author: pk;  state: Exp;  lines: +22 -22
	Add entries for Type5 keys T5_Insert, T5_Home, T5_End, T5_PgUp and T5_PgDn
	as suggested by uwe@netbsd.org.
	----------------------------

which is where the Up, Down, Right, and Left keys were fixed for type-5
(though oddly Home was not).

Ultimately we find the cause of my confusion:

	----------------------------
	revision 1.5
	date: 1997/10/28 06:18:36;  author: gwr;  state: Exp;  lines: +38 -38
	branches:  1.5.26;  1.5.28;
	The release and control maps are shared by all keyboard types, so
	change KEYSYM_HOLE to KEYSYM_NOP most places in those tables.
	Map the `R' function keys with KEYSYM_FUNC_R instead of the
	arrow key strings so that numlock indirection works.
	----------------------------

and indeed the delta includes these changes:

	***************
	*** 394 ****
	!     /*  69: R8/Up       */    KEYSYM_STRING | 1,
	--- 394 ----
	!     /*  69: R8/Up       */    KEYSYM_FUNC_R(8),
	***************
	*** 416 ****
	!     /*  91: R10/Left    */    KEYSYM_STRING | 3,
	--- 416 ----
	!     /*  91: R10/Left    */    KEYSYM_FUNC_R(10),
	***************
	*** 418 ****
	!     /*  93: R12/Right   */    KEYSYM_STRING | 4,
	--- 418 ----
	!     /*  93: R12/Right   */    KEYSYM_FUNC_R(12),
	***************
	*** 438 ****
	!     /* 113: R14/Down    */    KEYSYM_STRING | 2,
	--- 438 ----
	!     /* 113: R14/Down    */    KEYSYM_FUNC_R(14),

In this change the type-4 keypad mappings to KEYSYM_STRING entries was
removed.  That's why way back when an SS-1 was my desktop, and it was
running a really old kernel, it worked fine, but now the same keyboard
running a 1.6-branch kernel (now on an SS-20, though that doesn't
matter), does not have working console cursor keys.

I see that a "sun-type4" entry has been added to termcap.src.  This is a
work-around had, I'm guessing/hoping.  The correct fix is to find out
what that rev.1.5 comment above really means and then to fix the tables
properly again so that the arrow keys are by default mapped to their
proper KEYSYM_STRING values.  What does "numlock indirection" mean, and
how did it not work with the proper KEYSYM_STRING mappings in place?
Though I didn't use my console much (except under X11) when running the
old kernel, I don't remember having any problems with numlock either.

(another work-around hack would be to write a small program which does
the right ioctl(KIOCSKEY) on the console keyboard to undo the above
rev.1.5 changes and also to fix key 68 to be KEYSYM_STRING|0 too.....)

-- 
								Greg A. Woods

+1 416 218-0098;            <g.a.woods@ieee.org>;           <woods@robohack.ca>
Planix, Inc. <woods@planix.com>; VE3TCP; Secrets of the Weird <woods@weird.com>