[OpenBIOS] r676 - cpu/x86/pc/olpc dev

svn at openbios.org svn at openbios.org
Fri Oct 12 11:00:06 CEST 2007


Author: wmb
Date: 2007-10-12 11:00:06 +0200 (Fri, 12 Oct 2007)
New Revision: 676

Added:
   cpu/x86/pc/olpc/keymap.fth
   cpu/x86/pc/olpc/parsekbd.py
Modified:
   cpu/x86/pc/olpc/mfgdata.fth
   cpu/x86/pc/olpc/setwp.fth
   dev/pckbd.fth
Log:
OLPC trac #3985 - ASCII keymaps from the KA manufacturing data tag.


Added: cpu/x86/pc/olpc/keymap.fth
===================================================================
--- cpu/x86/pc/olpc/keymap.fth	                        (rev 0)
+++ cpu/x86/pc/olpc/keymap.fth	2007-10-12 09:00:06 UTC (rev 676)
@@ -0,0 +1,90 @@
+purpose: Populate keymaps from the KA manufacturing data tag
+\ See license at end of file
+
+\ Per http://wiki.laptop.org/Manufacturing_Data#Keyboard_ASCII_Map
+
+h# 60 constant /submap
+
+\ Special hack for the OLPC keyboard multiply/divide key, which is
+\ sometimes used for ASCII punctuation
+: ?multkey  ( scancode -- scancode' )
+   \ Translate down to the range that fits in the ASCII keymaps
+   dup h# 73 =  if  drop h# 5f   then
+;
+
+: !map  ( scancode ascii submap# -- )
+   /submap * rot  ?multkey  +  oem-keymap +  1+  c!
+;
+
+\ Clear out a range of map entries
+: zap  ( first last -- )
+   1+ swap  ?do  i 0 0 !map  i 0 1 !map  loop
+;
+
+: punctuation  " 0123456789!""#$%&'()*+,-./:;<=>?@[\]^_`{|}~"  drop  ;
+: fill-keymap  ( value$ -- )
+   oem-keymap /keymap 0 fill    ( adr len )
+   3 oem-keymap c!              ( adr len )  \ #submaps
+   \ Prime the shift and unshift maps with special characters
+   [ also keyboards ] us [ previous ]  3 +  oem-keymap 1+ /submap 2*  move
+
+   \ Clear out some the map entries for the alphanumeric/punctuation stations,
+   \ so we don't have confusing leftovers from the US map
+   2 h# d zap   h# 10 h# 1b zap  h# 1e h# 29 zap  h# 2b h# 35 zap
+
+   \ Set the a-z entries - assume unshifted and infer shifted
+   2dup d# 26 min  0  ?do   ( value$ adr )
+      dup i + c@            ( value$ adr scancode )
+      [char] a i +          ( value$ adr scancode ascii )
+      2dup 0 !map           ( value$ adr scancode ascii )  \ Unshifted
+      h# 20 xor  1 !map     ( value$ adr )   \ Shifted
+   loop                     ( value$ adr )
+   drop                     ( value$ )
+   dup d# 26 min /string    ( value$' )
+      
+   \ Set the 0-9 and punctuation entries in specifed maps
+   d# 42 min  0  ?do        ( adr )
+      dup  i 2* +           ( adr adr' )
+      dup c@                ( adr adr' scancode )
+      punctuation i + c@    ( adr adr' scancode ascii )
+      rot 1+ c@ !map        ( adr )
+   loop                     ( adr )
+   drop
+;
+
+\ If a KA tag is present, parse it into a keymap
+: olpc-keymap?  ( -- got? )
+   " KA" " find-tag" eval  if  ( value$ )
+      ?free-keymap
+      /keymap alloc-mem to oem-keymap                ( adr' len' )
+      fill-keymap
+      oem-keymap to keymap
+      true
+   else
+      false
+   then
+;
+
+\ LICENSE_BEGIN
+\ Copyright (c) 2007 FirmWorks
+\ 
+\ Permission is hereby granted, free of charge, to any person obtaining
+\ a copy of this software and associated documentation files (the
+\ "Software"), to deal in the Software without restriction, including
+\ without limitation the rights to use, copy, modify, merge, publish,
+\ distribute, sublicense, and/or sell copies of the Software, and to
+\ permit persons to whom the Software is furnished to do so, subject to
+\ the following conditions:
+\ 
+\ The above copyright notice and this permission notice shall be
+\ included in all copies or substantial portions of the Software.
+\ 
+\ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+\ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+\ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+\ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+\ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+\ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+\ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+\
+\ LICENSE_END

Modified: cpu/x86/pc/olpc/mfgdata.fth
===================================================================
--- cpu/x86/pc/olpc/mfgdata.fth	2007-10-12 00:11:50 UTC (rev 675)
+++ cpu/x86/pc/olpc/mfgdata.fth	2007-10-12 09:00:06 UTC (rev 676)
@@ -9,23 +9,39 @@
 : invalid-tag?  ( adr -- data-adr flag )
    -1 hibit?  if  true exit  then  \ Name char must be 7-bit ASCII
    -2 hibit?  if  true exit  then  \ Name char must be 7-bit ASCII
-   -3 hibit?  if  true exit  then  \ Length must be 7 bits
-   dup  3 - c@                          ( adr len )
-   over 4 - c@                          ( adr len ~len )
-   xor  h# ff <>  if  true exit  then   ( adr )
-   dup  3 - c@  - 4 -                   ( adr' )
+   -3 hibit?  if  \ Long (5-byte tag) format   ( adr )
+      dup  4 - c@  dup h# 80 and  if  drop true exit  then   ( adr low )
+      over 5 - c@  dup h# 80 and  if  2drop true exit  then  ( adr low high )
+      2dup xor h# ff xor                                     ( adr low high check )
+      3 pick 3 - c@ <>  if  3drop true exit  then            ( adr low high )
+      7 << +                                                 ( adr length )
+      - 5 -                                                  ( data-adr )
+   else           \ Short (4-byte tag) format
+      dup  3 - c@                          ( adr len )
+      over 4 - c@                          ( adr len ~len )
+      xor  h# ff <>  if  true exit  then   ( adr )
+      dup  3 - c@  - 4 -                   ( data-adr )
+   then
+
    false
 ;
 
 : last-mfg-data  ( top-adr -- adr )  begin  invalid-tag?  until  ;
 
 : another-tag?  ( adr -- adr false |  adr' data$ name-adr true )
-   dup invalid-tag?  if   ( adr data-adr )
+   dup invalid-tag?  if       ( adr data-adr )
       drop false exit
-   then                   ( adr data-adr )
-   dup rot                ( data-adr data-adr adr )
-   2dup swap - 4 -        ( data-adr data-adr adr data-len )
-   swap 2-  true          ( adr' data$ adr )
+   then                       ( adr data-adr )
+   >r  2-                     ( name-adr r: data-adr )
+   dup 1- c@ h# 80 and  if    ( name-adr r: data-adr )   \ 5-byte format
+      dup 2- c@               ( name-adr lowlen r: data-adr )
+      over 3 - c@  7 lshift + ( name-adr len r: data-adr )
+   else                       ( name-adr r: data-adr )   \ 4-byte format
+      dup 1- c@               ( name-adr len r: data-adr )
+   then                       ( name-adr len r: data-adr )
+   r> rot >r                  ( len data-adr r: name-adr )
+   dup rot  r>                ( adr data$ name-adr )
+   true                       ( adr data$ name-adr true )
 ;
 
 \ Mfg data used to be at the end of the EC erase block, but

Added: cpu/x86/pc/olpc/parsekbd.py
===================================================================
--- cpu/x86/pc/olpc/parsekbd.py	                        (rev 0)
+++ cpu/x86/pc/olpc/parsekbd.py	2007-10-12 09:00:06 UTC (rev 676)
@@ -0,0 +1,219 @@
+#!/usr/bin/python
+# parsekbd.py
+# Usage:  python parsekbd.py OLPC_Nigeria_Keyboard
+#
+# Gets the wiki page (e.g.) http://wiki.laptop.org/go/OLPC_Nigeria_Keyboard
+# Parses the keyboard table contained therein and converts it to a KA
+# tag per http://wiki.laptop.org/go/Manufacturing_Data#Keyboard_ASCII_Map.
+#
+# The output is stored in a file named (e.g.) OLPC_Nigeria_Keyboard.ka
+#
+# Warnings on standard output tell you if duplicate entries are discarded
+# or if some ASCII characters are not present.
+#
+# In a few cases, this program substitutes dead_{grave,circumflex,tilde}
+# for {grave,asciicircumflex,asciitilde} because the ascii versions are
+# in inaccessible locations (the firmware has only shift, unshift, AltGr
+# maps, so a Shift-AltGr symbol is inaccessible).
+
+from sys import *
+from urllib import *
+from HTMLParser import HTMLParser
+
+state = 0
+keys = 128*[0]
+modifiers = 128*[0]
+column = 0
+keyid = 0
+
+# Convert from textual names of punctuation characters to the ASCII character
+punctuation = {
+  'exclam':ord('!'),
+  'at':ord('@'),
+  'numbersign':ord('#'),
+  'dollar':ord('$'),
+  'percent':ord('%'),
+  'asciicircum':ord('^'),
+  'dead_circumflex':ord('^'),
+  'ampersand':ord('&'),
+  'asterisk':ord('*'),
+  'parenleft':ord('('),
+  'parenright':ord(')'),
+  'underscore':ord('_'),
+  'plus':ord('+'),
+  'minus':ord('-'),
+  'equal':ord('='),
+  'semicolon':ord(';'),
+  'colon':ord(':'),
+  'apostrophe':ord('\''),
+  'grave':ord('`'),
+  'dead_grave':ord('`'),
+  'quotedbl':ord('"'),
+  'dblquote':ord('"'),
+  'bar':ord('|'),
+  'less':ord('<'),
+  'greater':ord('>'),
+  'period':ord('.'),
+  'slash':ord('/'),
+  'backslash':ord('\\'),
+  'question':ord('?'),
+  'comma':ord(','),
+  'bracketleft':ord('['),
+  'bracketright':ord(']'),
+  'braceleft':ord('{'),
+  'braceright':ord('}'),
+  'asciitilde':ord('~') ,
+  'dead_tilde':ord('~') ,
+  'backspace':8,
+  'space':32,
+  'tab':9,
+  'linefeed':10,
+  'enter':13,
+  'esc':27,
+  'escape':27,
+  'del':127,
+  'delete':127,
+  '&amp;':ord('&'),
+  '&lt;':ord('<'),
+  '&gt;':ord('>'),
+}
+
+def string_to_ascii(s):
+        if len(s) == 0:
+                return -1
+        if len(s) == 1:
+                return ord(s)
+        try:
+                i = punctuation[s]
+                return i
+        except:
+                pass
+        if (len(s) == 3) & (s[:2] == 'C-'):
+                return ord(s[2]) & 0x1f
+        return -1
+
+def handle_key(modifier, s):
+        global keyid
+        ascii = string_to_ascii(s)
+        if ascii == -1:
+                return
+        if keys[ascii] != 0:
+                if (ascii >= 0x20) & (((modifier & 1) == 0) & (keys[ascii] != keyid)):
+                        print "Discard",hex(ascii),chr(ascii),modifier,keyid,modifiers[keyid]
+                return
+        if ascii < 0x20:
+                if (modifier & 2) != 0:   # ctrl
+                        if keys[ascii + 0x60] == keyid:
+                                return
+                        if keys[ascii + 0x40] == keyid:
+                                return
+        keys[ascii] = keyid
+        modifiers[ascii] = modifier
+
+class MyHTMLParser(HTMLParser):
+    def handle_starttag(self, tag, attrs):
+        global state, column, keyid
+        if tag == 'table':
+                state = state + 1
+        elif tag == 'tr':
+                column = 0
+                keyid = 0
+        elif tag == 'td':
+                column = column + 1;
+    
+    def handle_data(self, data):
+        global state, column, keyid
+        if state != 1:
+                return
+        s = data.strip()
+        if column == 1:    # XKB key
+                pass
+        elif column == 2:  # HID
+                pass
+        elif column == 3:  # Key
+                if s.isdigit():
+                        keyid = int(s)
+        elif column == 4:  # Unmodified
+                handle_key(0,s)
+        elif column == 5:  # Shift
+                handle_key(1,s)
+        elif column == 6:  # AltGR
+                handle_key(4,s)
+        elif column == 7:  # Shift AltGr
+                # handle_key(5,s)
+                pass
+        elif column == 8:  # Ctrl
+                handle_key(2,s)
+        elif column == 9:  # Fn
+                handle_key(8,s)
+        elif column == 10:  # comment
+                pass
+
+
+# This table converts from the IBM physical keystation number to
+# the corresponding scancode value in scan set 1.
+
+#   0     1     3     3     4     5     6     7     8     9
+scan1_map = [
+ 0x00, 0x29, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09,    # 0x
+ 0x0a, 0x0b, 0x0c, 0x0d, 0x00, 0x0e, 0x0f, 0x10, 0x11, 0x12,    # 1x
+ 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x2b,    # 2x
+ 0x3a, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26,    # 3x
+ 0x27, 0x28, 0x2b, 0x1c, 0x2a, 0x56, 0x2c, 0x2d, 0x2e, 0x2f,    # 4x
+ 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x73, 0x36, 0x1d, 0x00,    # 5x
+ 0x38, 0x39, 0x38, 0x00, 0x1d, 0x00, 0x00, 0x00, 0x00, 0x00,    # 6x
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,    # 7x
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,    # 8x
+ 0x45, 0x47, 0x4B, 0x4F, 0x00, 0x00, 0x48, 0x4C, 0x50, 0x52,    # 9x
+ 0x37, 0x49, 0x4D, 0x51, 0x53, 0x4A, 0x4E, 0x00, 0x1c, 0x00,    # 10x 
+ 0x01, 0x00, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, 0x40, 0x41, 0x42,    # 11x
+ 0x43, 0x44, 0x57, 0x58, 0x00, 0x46, 0x00, 0x00, 0x00, 0x00,    # 12x
+ 0x79, 0x01, 0x00, 0x5c, 0x73, 0x6e, 0x00, 0x00, 0x00, 0x00,    # 13x (analog intermediates)
+ 0x00, 0x00, 0x00, 0x00, 0x00,                                  # 14x
+]
+
+def put_ka_format(outfile):
+        global keys, modifiers
+        # a-z - output scancode only; unshifted map is implied
+        # and shifted map is derived automatically
+        for i in range(ord('a'),ord('a')+26):
+                if (keys[i] == 0):
+                        print "Missing",chr(i)
+                if modifiers[i] != 0:
+                        print chr(i),"is modified"
+                outfile.write(chr(scan1_map[keys[i]]))
+        
+        # Numbers and punctuation - output scancode and keymap number
+        for i in '0123456789!"#$%&\'()*+,-./:;<=>?@[\\]^_`{|}~':
+                ascii = ord(i)
+                if (keys[ascii] == 0):
+                        print "Missing",i
+                if (modifiers[ascii] & 0xa) != 0:
+                        print i,"is Ctrl or Fn"
+                outfile.write(chr(scan1_map[keys[ascii]]))
+                
+                if (modifiers[ascii] & 0x4) != 0:
+                        # modifier & 4 implies AltGr map
+                        outfile.write(chr(2))
+                else:
+                        # otherwise it's either the shift (1) or unshift (0) map
+                        outfile.write(chr(modifiers[ascii] & 1))
+        
+        outfile.write(chr(0))   # Null terminator
+        
+        outfile.write(chr(111 ^ 0xff))
+        outfile.write(chr(111))
+        outfile.write('KA')
+
+if len(argv) != 2:
+        print "Usage: python parsekbd.py PageName"
+else:
+        infile = urlopen('http://wiki.laptop.org/go/' + argv[1])
+        myparser=MyHTMLParser()
+        myparser.feed(infile.read())
+        myparser.close()
+        infile.close()
+        
+        outfile = open(argv[1] + '.ka', 'w')
+        put_ka_format(outfile)
+        outfile.close()


Property changes on: cpu/x86/pc/olpc/parsekbd.py
___________________________________________________________________
Name: svn:executable
   + *

Modified: cpu/x86/pc/olpc/setwp.fth
===================================================================
--- cpu/x86/pc/olpc/setwp.fth	2007-10-12 00:11:50 UTC (rev 675)
+++ cpu/x86/pc/olpc/setwp.fth	2007-10-12 09:00:06 UTC (rev 676)
@@ -117,19 +117,57 @@
 : $add-tag  ( value$ name$ -- )
    ?tagname-valid                                 ( value$ name$ )
    2dup find-tag  abort" Tagname already exists"  ( value$ name$ )
+
    get-mfg-data
    ram-last-mfg-data  >r                          ( value$ name$ r: adr )
-   2 pick 1+  over +  3 +                         ( value$ name$ record-len r: adr )
+
+   \ Check for enough space for the new tag
+   2 pick                                         ( value$ name$ datalen r: adr )
+   dup d# 16383 >  abort" Tag data too long"
+   dup d# 127 >  if  4  else  3  then  +          ( value$ name$ datalen' r: adr )
+   over +                                         ( value$ name$ record-len r: adr )
    r@ over -  mfg-data-buf u<=  abort" Not enough space for new tag"
+
+   \ Ensure that the space is not being used for something else
    r@ over -  swap  ?erased                       ( value$ name$ r: adr )
+
+   \ Copy the tag name
    r@ 2- swap move                                ( value$ r: adr )
-   dup 1+  dup r@ 3 - c!  invert r@ 4 - c!        ( value$ r: adr )
-   0  r@ 5 - c!                                   ( value$ r: adr )
-   r> 5 -  over -                                 ( value$ data-adr )
-   swap move
-   put-mfg-data
+
+   \ Set the length field
+   dup                                            ( value$ len r: adr )
+   dup d# 127 >  if                               ( value$ len r: adr )
+      \ 5-byte tag format - (top) check, lowlen, highlen (bottom)
+      dup 7 rshift  swap h# 7f and                ( value$ len-high len-low r: adr )
+      2dup xor  h# ff xor                         ( value$ len-high len-low check r: adr )
+      r@ 3 - c!  r@ 4 - c!  r@ 5 - c!             ( value$ r: adr )
+      r> 5 -                                      ( value$ end-adr )
+   else                                           ( value$ len' r: adr )
+      \ 4-byte tag format - (top) len, ~len (bottom)
+      dup r@ 3 - c!  invert r@ 4 - c!             ( value$ r: adr )
+      r> 4 -                                      ( value$ end-adr )
+   then                                           ( value$ end-adr )
+
+   \ Copy the value data
+   over -  swap move                              ( )
+
+   put-mfg-data                                   ( )
 ;
 
+: add-null  ( adr len -- adr' len' )  $cstr  cscount 1+   ;
+
 : add-tag  ( "name$" "value$" -- )
-   safe-parse-word  0 parse  2swap $add-tag
+   safe-parse-word  0 parse add-null  2swap $add-tag
 ;
+
+: $delete-tag  ( name$ -- )
+   tag-setup                    ( ram-value$ )
+   2dup + c@ h# 80 and          ( ram-value$ tag-style )
+   if  4  else  5  then  +  >r  ( tag-adr tag-len )
+   ram-last-mfg-data  >r        ( tag-adr r: len bot-adr ) 
+   r@  2r@ +                    ( tag-adr src-adr dst-adr r: len bot-adr )    
+   rot r@ -                     ( src-adr dst-adr copy-len r: len bot-adr ) 
+   move                         ( r: len bot-adr )
+   r> r> h# ff fill             ( )
+   put-mfg-data
+;

Modified: dev/pckbd.fth
===================================================================
--- dev/pckbd.fth	2007-10-12 00:11:50 UTC (rev 675)
+++ dev/pckbd.fth	2007-10-12 09:00:06 UTC (rev 676)
@@ -211,6 +211,21 @@
    oem-keymap  if  oem-keymap  /keymap  free-mem  then
    0 to oem-keymap
 ;
+[ifdef] olpc
+: ?olpc-keyboard  ( -- )
+    " enable-intf" $call-parent
+    begin  get-data?  while
+       drop
+       true to keyboard-present?
+       5 ms
+    repeat
+    keyboard-present?  if  exit  then
+    kbd-reset 0= to keyboard-present?
+;
+
+fload ${BP}/cpu/x86/pc/olpc/keymap.fth
+[then]
+
 : choose-type  ( -- )
    my-args  dup  if
       [char] , left-parse-string  2swap 2drop  ( $ )
@@ -231,6 +246,10 @@
       exit
    then
 
+[ifdef] olpc-keymap?
+   olpc-keymap?  if  exit  then
+[then]
+
    " us" set-keyboard
 \    pc-keyboard-type set-keyboard
 ;
@@ -335,21 +354,10 @@
    false
 ;
 
-: ?olpc-keyboard  ( -- )
-    " enable-intf" $call-parent
-    begin  get-data?  while
-       drop
-       true to keyboard-present?
-       5 ms
-    repeat
-    keyboard-present?  if  exit  then
-    kbd-reset 0= to keyboard-present?
-;
-
 : reset  ( -- )
    init-data
    clear-state
-[ifdef] olpc
+[ifdef] ?olpc-keyboard
    ?olpc-keyboard
 [else]
    get-initial-state
@@ -677,6 +685,8 @@
    \ Split the scancode into the up/down indicator and the key identifier
    h# 80 /mod 0=  swap                           ( down? scan )
 	
+[ifdef] ?multkey  ?multkey  [then]
+
    \ Exit if the scancode is one that is never used for ASCII characters
    dup h# 60 >=  if  2drop  false  exit  then    ( down? scan )
 




More information about the OpenBIOS mailing list