[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,
+ '&':ord('&'),
+ '<':ord('<'),
+ '>':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