Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Mapping characters to keycodes for international keysets

so I built a pi zero keyboard emulator as mentioned here:

https://www.rmedgar.com/blog/using-rpi-zero-as-keyboard-setup-and-device-definition

I make it type text that it reads from a local text-file (everything developed in java - for reasons :) ).
My problem now is that the configured keysets on the various computers my pi zero is attached to differ very much (german, english, french, ...). Depending on the computer this leads to several typing mistakes (e.g., z instead of y).

So I now built some "translation tables" that map characters to the keycodes fitting to the computer. Such a table looks like this:

public scancodes_en_us() {
    //We have (Character, (scancode, modifier))
    table.put("a",Pair.create("4","0"));
    table.put("b",Pair.create("5","0"));
    table.put("c",Pair.create("6","0"));
    table.put("d",Pair.create("7","0"));
    table.put("e",Pair.create("8","0"));
    table.put("f",Pair.create("9","0"));
    table.put("g",Pair.create("10","0"));
    table.put("h",Pair.create("11","0"));
    table.put("i",Pair.create("12","0"));
    table.put("j",Pair.create("13","0"));
    table.put("k",Pair.create("14","0"));
    table.put("l",Pair.create("15","0"));
    table.put("m",Pair.create("16","0"));
    table.put("n",Pair.create("17","0"));
    table.put("o",Pair.create("18","0"));
    table.put("p",Pair.create("19","0"));
    table.put("q",Pair.create("20","0"));
    table.put("r",Pair.create("21","0"));
    table.put("s",Pair.create("22","0"));
    table.put("t",Pair.create("23","0"));
    table.put("u",Pair.create("24","0"));
    table.put("v",Pair.create("25","0"));
    table.put("w",Pair.create("26","0"));
    table.put("x",Pair.create("27","0"));
    table.put("y",Pair.create("28","0"));
    table.put("z",Pair.create("29","0"));
    table.put("A",Pair.create("4","2"));
    table.put("B",Pair.create("5","2"));
    table.put("C",Pair.create("6","2"));
    table.put("D",Pair.create("7","2"));
    table.put("E",Pair.create("8","2"));
    table.put("F",Pair.create("9","2"));
    table.put("G",Pair.create("10","2"));
    table.put("H",Pair.create("11","2"));
    table.put("I",Pair.create("12","2"));
    table.put("J",Pair.create("13","2"));
    table.put("K",Pair.create("14","2"));
    table.put("L",Pair.create("15","2"));
    table.put("M",Pair.create("16","2"));
    table.put("N",Pair.create("17","2"));
    table.put("O",Pair.create("18","2"));
    table.put("P",Pair.create("19","2"));
    table.put("Q",Pair.create("20","2"));
    table.put("R",Pair.create("21","2"));
    table.put("S",Pair.create("22","2"));
    table.put("V",Pair.create("25","2"));
    table.put("W",Pair.create("26","2"));
    table.put("X",Pair.create("27","2"));
    table.put("Y",Pair.create("28","2"));
    table.put("Z",Pair.create("29","2"));
    table.put("1",Pair.create("30","0"));
    table.put("2",Pair.create("31","0"));
    table.put("5",Pair.create("34","0"));
    table.put("6",Pair.create("35","0"));
    table.put("7",Pair.create("36","0"));
    table.put("8",Pair.create("37","0"));
    table.put("9",Pair.create("38","0"));
    table.put("0",Pair.create("39","0"));
    table.put("!",Pair.create("30","2"));
    table.put("@",Pair.create("31","2"));
    table.put("#",Pair.create("32","2"));
    table.put("$",Pair.create("33","2"));
    table.put("%",Pair.create("34","2"));
    table.put("^",Pair.create("35","2"));
    table.put("&",Pair.create("36","2"));
    table.put("*",Pair.create("37","2"));
    table.put("(",Pair.create("38","2"));
    table.put(")",Pair.create("39","2"));
    table.put(" ",Pair.create("44","0"));
    table.put("-",Pair.create("45","0"));
    table.put("=",Pair.create("46","0"));
    table.put("[",Pair.create("47","0"));
    table.put("]",Pair.create("48","0"));
    table.put("\\",Pair.create("49","0"));
    table.put(";",Pair.create("51","0"));
    table.put("'",Pair.create("52","0"));
    table.put("`",Pair.create("53","0"));
    table.put(",",Pair.create("54","0"));
    table.put(".",Pair.create("55","0"));
    table.put("/",Pair.create("56","0"));
    table.put("_",Pair.create("45","2"));
    table.put("+",Pair.create("46","2"));
    table.put("{",Pair.create("47","2"));
    table.put("}",Pair.create("48","2"));
    table.put("|",Pair.create("49","2"));
    table.put(":",Pair.create("51","2"));
    table.put("\"",Pair.create("52","2"));
    table.put("~",Pair.create("53","2"));
    table.put("<",Pair.create("54","2"));
    table.put(">",Pair.create("55","2"));
    table.put("?",Pair.create("56","2"));

Having such a table for many different keyboard layouts is a pain. Is there some more clever version to map a character to the scancode for a specific keyboard layout?

If not - is there some kind of archive where I can find such a character to scancode mapping for many different keyboard layouts?

Thank you very much

like image 351
pinas Avatar asked Jun 07 '18 14:06

pinas


2 Answers

Look at how localization works, they all share the same approach: Create a special version for each localization as a property file, then have an abstract class to load the property based on locale.

You will develop a loader class like this:

public scancodes(Locale locale) {
    // load locale property file or download if missing
    // read the property and store to the table
    ResourceBundle scanCodes = ResourceBundle.getBundle("codes",locale);
}

And your codes_locale looks like:

codes_de.properties

a=4,0
b=5,0

By doing this, you separate the locale specific character with your logic code, and you don't need to bundle all keyboards in side your app. You can download them as needed.

You can access a tutorial here

like image 143
Mạnh Quyết Nguyễn Avatar answered Oct 03 '22 10:10

Mạnh Quyết Nguyễn


If I understood what you are trying to do correctly then you don't have to map anything at all, just use a pre-made format (like unicode which works for all languages I know of), just send a char code and translate it to it's matching char.

Example file reader - char interpreter:

JFileChooser fc = new JFileChooser();
fc.setFileSelectionMode(JFileChooser.FILES_ONLY);
fc.showOpenDialog(null);

File textFile = fc.getSelectedFile();

if(textFile.getName().endsWith(".txt")) {
    System.out.println(textFile.getAbsolutePath());
    FileInputStream input = new FileInputStream(textFile);
    BufferedReader reader = new BufferedReader(new InputStreamReader(input, "UNICODE"));
    char[] buffer = new char[input.available() / 2 - 1];
    System.out.println("Bytes left: " + input.available());
    int read = reader.read(buffer);
    System.out.println("Read " + read + " characters");
    for(int i = 0; i < read; i++) {
        System.out.print("The letter is: " + buffer[i]);
        System.out.println(", The key code is: " + (int) buffer[i]);
    }
}

you can later use the key code to emulate a key press on your computer

like image 29
OE.omergunr100 Avatar answered Oct 03 '22 09:10

OE.omergunr100