Annotation of qemu/roms/ipxe/src/util/genkeymap.pl, revision 1.1.1.1

1.1       root        1: #!/usr/bin/perl -w
                      2: #
                      3: # Copyright (C) 2011 Michael Brown <[email protected]>.
                      4: #
                      5: # This program is free software; you can redistribute it and/or
                      6: # modify it under the terms of the GNU General Public License as
                      7: # published by the Free Software Foundation; either version 2 of the
                      8: # License, or any later version.
                      9: #
                     10: # This program is distributed in the hope that it will be useful, but
                     11: # WITHOUT ANY WARRANTY; without even the implied warranty of
                     12: # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
                     13: # General Public License for more details.
                     14: #
                     15: # You should have received a copy of the GNU General Public License
                     16: # along with this program; if not, write to the Free Software
                     17: # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
                     18: 
                     19: =head1 NAME
                     20: 
                     21: genkeymap.pl
                     22: 
                     23: =head1 SYNOPSIS
                     24: 
                     25: genkeymap.pl [options] <keymap name>
                     26: 
                     27: Options:
                     28: 
                     29:     -f,--from=<name>   Set BIOS keymap name (default "us")
                     30:     -h,--help          Display brief help message
                     31:     -v,--verbose       Increase verbosity
                     32:     -q,--quiet         Decrease verbosity
                     33: 
                     34: =cut
                     35: 
                     36: # With reference to:
                     37: #
                     38: # http://gunnarwrobel.de/wiki/Linux-and-the-keyboard.html
                     39: 
                     40: use Getopt::Long;
                     41: use Pod::Usage;
                     42: use strict;
                     43: use warnings;
                     44: 
                     45: use constant BIOS_KEYMAP => "us";
                     46: use constant BKEYMAP_MAGIC => "bkeymap";
                     47: use constant MAX_NR_KEYMAPS => 256;
                     48: use constant NR_KEYS => 128;
                     49: use constant KG_SHIFT => 0;
                     50: use constant KG_ALTGR => 1;
                     51: use constant KG_CTRL => 2;
                     52: use constant KG_ALT => 3;
                     53: use constant KG_SHIFTL => 4;
                     54: use constant KG_KANASHIFT => 4;
                     55: use constant KG_SHIFTR => 5;
                     56: use constant KG_CTRLL => 6;
                     57: use constant KG_CTRLR => 7;
                     58: use constant KG_CAPSSHIFT => 8;
                     59: use constant KT_LATIN => 0;
                     60: use constant KT_FN => 1;
                     61: use constant KT_SPEC => 2;
                     62: use constant KT_PAD => 3;
                     63: use constant KT_DEAD => 4;
                     64: use constant KT_CONS => 5;
                     65: use constant KT_CUR => 6;
                     66: use constant KT_SHIFT => 7;
                     67: use constant KT_META => 8;
                     68: use constant KT_ASCII => 9;
                     69: use constant KT_LOCK => 10;
                     70: use constant KT_LETTER => 11;
                     71: use constant KT_SLOCK => 12;
                     72: use constant KT_SPKUP => 14;
                     73: 
                     74: my $verbosity = 1;
                     75: my $from_name = BIOS_KEYMAP;
                     76: 
                     77: # Read named keymaps using "loadkeys -b"
                     78: #
                     79: sub read_keymaps {
                     80:   my $name = shift;
                     81:   my $keymaps = [];
                     82: 
                     83:   # Generate binary keymap
                     84:   open my $pipe, "-|", "loadkeys", "-b", $name
                     85:       or die "Could not load keymap \"".$name."\": $!\n";
                     86: 
                     87:   # Check magic
                     88:   read $pipe, my $magic, length BKEYMAP_MAGIC
                     89:       or die "Could not read from \"".$name."\": $!\n";
                     90:   die "Bad magic value from \"".$name."\"\n"
                     91:       unless $magic eq BKEYMAP_MAGIC;
                     92: 
                     93:   # Read list of included keymaps
                     94:   read $pipe, my $included, MAX_NR_KEYMAPS
                     95:       or die "Could not read from \"".$name."\": $!\n";
                     96:   my @included = unpack ( "C*", $included );
                     97:   die "Missing or truncated keymap list from \"".$name."\"\n"
                     98:       unless @included == MAX_NR_KEYMAPS;
                     99: 
                    100:   # Read each keymap in turn
                    101:   for ( my $keymap = 0 ; $keymap < MAX_NR_KEYMAPS ; $keymap++ ) {
                    102:     if ( $included[$keymap] ) {
                    103:       read $pipe, my $keysyms, ( NR_KEYS * 2 )
                    104:          or die "Could not read from \"".$name."\": $!\n";
                    105:       my @keysyms = unpack ( "S*", $keysyms );
                    106:       die "Missing or truncated keymap ".$keymap." from \"".$name."\"\n"
                    107:          unless @keysyms == NR_KEYS;
                    108:       push @$keymaps, \@keysyms;
                    109:     } else {
                    110:       push @$keymaps, undef;
                    111:     }
                    112:   }
                    113: 
                    114:   close $pipe;
                    115:   return $keymaps;
                    116: }
                    117: 
                    118: # Translate keysym value to ASCII
                    119: #
                    120: sub keysym_to_ascii {
                    121:   my $keysym = shift;
                    122: 
                    123:   # Non-existent keysyms have no ASCII equivalent
                    124:   return unless $keysym;
                    125: 
                    126:   # Sanity check
                    127:   die "Unexpected keysym ".sprintf ( "0x%04x\n", $keysym )."\n"
                    128:       if $keysym & 0xf000;
                    129: 
                    130:   # Extract type and value
                    131:   my $type = ( $keysym >> 8 );
                    132:   my $value = ( $keysym & 0xff );
                    133: 
                    134:   # Non-simple types have no ASCII equivalent
                    135:   return unless ( ( $type == KT_LATIN ) || ( $type == KT_ASCII ) ||
                    136:                  ( $type == KT_LETTER ) );
                    137: 
                    138:   # High-bit-set characters cannot be generated on a US keyboard
                    139:   return if $value & 0x80;
                    140: 
                    141:   return $value;
                    142: }
                    143: 
                    144: # Translate ASCII to descriptive name
                    145: #
                    146: sub ascii_to_name {
                    147:   my $ascii = shift;
                    148: 
                    149:   if ( $ascii == 0x5c ) {
                    150:     return "'\\\\'";
                    151:   } elsif ( $ascii == 0x27 ) {
                    152:     return "'\\\''";
                    153:   } elsif ( ( $ascii >= 0x20 ) && ( $ascii <= 0x7e ) ) {
                    154:     return sprintf ( "'%c'", $ascii );
                    155:   } elsif ( $ascii <= 0x1a ) {
                    156:     return sprintf ( "Ctrl-%c", ( 0x40 + $ascii ) );
                    157:   } else {
                    158:     return sprintf ( "0x%02x", $ascii );
                    159:   }
                    160: }
                    161: 
                    162: # Produce translation table between two keymaps
                    163: #
                    164: sub translate_keymaps {
                    165:   my $from = shift;
                    166:   my $to = shift;
                    167:   my $map = {};
                    168: 
                    169:   foreach my $keymap ( 0, 1 << KG_SHIFT, 1 << KG_CTRL ) {
                    170:     for ( my $keycode = 0 ; $keycode < NR_KEYS ; $keycode++ ) {
                    171:       my $from_ascii = keysym_to_ascii ( $from->[$keymap]->[$keycode] )
                    172:          or next;
                    173:       my $to_ascii = keysym_to_ascii ( $to->[$keymap]->[$keycode] )
                    174:          or next;
                    175:       my $new_map = ( ! exists $map->{$from_ascii} );
                    176:       my $update_map =
                    177:          ( $new_map || ( $keycode < $map->{$from_ascii}->{keycode} ) );
                    178:       if ( ( $verbosity > 1 ) &&
                    179:           ( ( $from_ascii != $to_ascii ) ||
                    180:             ( $update_map && ! $new_map ) ) ) {
                    181:        printf STDERR "In keymap %d: %s => %s%s\n", $keymap,
                    182:               ascii_to_name ( $from_ascii ), ascii_to_name ( $to_ascii ),
                    183:               ( $update_map ? ( $new_map ? "" : " (override)" )
                    184:                             : " (ignored)" );
                    185:       }
                    186:       if ( $update_map ) {
                    187:        $map->{$from_ascii} = {
                    188:          to_ascii => $to_ascii,
                    189:          keycode => $keycode,
                    190:        };
                    191:       }
                    192:     }
                    193:   }
                    194:   return { map { $_ => $map->{$_}->{to_ascii} } keys %$map };
                    195: }
                    196: 
                    197: # Parse command-line options
                    198: Getopt::Long::Configure ( 'bundling', 'auto_abbrev' );
                    199: GetOptions (
                    200:   'verbose|v+' => sub { $verbosity++; },
                    201:   'quiet|q+' => sub { $verbosity--; },
                    202:   'from|f=s' => sub { shift; $from_name = shift; },
                    203:   'help|h' => sub { pod2usage ( 1 ); },
                    204: ) or die "Could not parse command-line options\n";
                    205: pod2usage ( 1 ) unless @ARGV == 1;
                    206: my $to_name = shift;
                    207: 
                    208: # Read and translate keymaps
                    209: my $from = read_keymaps ( $from_name );
                    210: my $to = read_keymaps ( $to_name );
                    211: my $map = translate_keymaps ( $from, $to );
                    212: 
                    213: # Generate output
                    214: ( my $to_name_c = $to_name ) =~ s/\W/_/g;
                    215: printf "/** \@file\n";
                    216: printf " *\n";
                    217: printf " * \"".$to_name."\" keyboard mapping\n";
                    218: printf " *\n";
                    219: printf " * This file is automatically generated; do not edit\n";
                    220: printf " *\n";
                    221: printf " */\n";
                    222: printf "\n";
                    223: printf "FILE_LICENCE ( PUBLIC_DOMAIN );\n";
                    224: printf "\n";
                    225: printf "#include <ipxe/keymap.h>\n";
                    226: printf "\n";
                    227: printf "/** \"".$to_name."\" keyboard mapping */\n";
                    228: printf "struct key_mapping ".$to_name_c."_mapping[] __keymap = {\n";
                    229: foreach my $from_sym ( sort { $a <=> $b } keys %$map ) {
                    230:   my $to_sym = $map->{$from_sym};
                    231:   next if $from_sym == $to_sym;
                    232:   printf "\t{ 0x%02x, 0x%02x },\t/* %s => %s */\n", $from_sym, $to_sym,
                    233:         ascii_to_name ( $from_sym ), ascii_to_name ( $to_sym );
                    234: }
                    235: printf "};\n";

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.