Annotation of qemu/roms/ipxe/src/util/genkeymap.pl, revision 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.