diff options
Diffstat (limited to 'hw/char/escc.c')
-rw-r--r-- | hw/char/escc.c | 79 |
1 files changed, 78 insertions, 1 deletions
diff --git a/hw/char/escc.c b/hw/char/escc.c index 17a908c59b..4f3872bfe9 100644 --- a/hw/char/escc.c +++ b/hw/char/escc.c @@ -31,6 +31,8 @@ #include "qemu/module.h" #include "hw/char/escc.h" #include "ui/console.h" + +#include "qemu/cutils.h" #include "trace.h" /* @@ -190,6 +192,7 @@ #define R_MISC1I 14 #define R_EXTINT 15 +static uint8_t sunkbd_layout_dip_switch(const char *sunkbd_layout); static void handle_kbd_command(ESCCChannelState *s, int val); static int serial_can_receive(void *opaque); static void serial_receive_byte(ESCCChannelState *s, int ch); @@ -846,6 +849,79 @@ static QemuInputHandler sunkbd_handler = { .event = sunkbd_handle_event, }; +static uint8_t sunkbd_layout_dip_switch(const char *kbd_layout) +{ + /* Return the value of the dip-switches in a SUN Type 5 keyboard */ + static uint8_t ret = 0xff; + + if ((ret == 0xff) && kbd_layout) { + int i; + struct layout_values { + const char *lang; + uint8_t dip; + } languages[] = + /* + * Dip values from table 3-16 Layouts for Type 4, 5 and 5c Keyboards + */ + { + {"en-us", 0x21}, /* U.S.A. (US5.kt) */ + /* 0x22 is some other US (US_UNIX5.kt) */ + {"fr", 0x23}, /* France (France5.kt) */ + {"da", 0x24}, /* Denmark (Denmark5.kt) */ + {"de", 0x25}, /* Germany (Germany5.kt) */ + {"it", 0x26}, /* Italy (Italy5.kt) */ + {"nl", 0x27}, /* The Netherlands (Netherland5.kt) */ + {"no", 0x28}, /* Norway (Norway.kt) */ + {"pt", 0x29}, /* Portugal (Portugal5.kt) */ + {"es", 0x2a}, /* Spain (Spain5.kt) */ + {"sv", 0x2b}, /* Sweden (Sweden5.kt) */ + {"fr-ch", 0x2c}, /* Switzerland/French (Switzer_Fr5.kt) */ + {"de-ch", 0x2d}, /* Switzerland/German (Switzer_Ge5.kt) */ + {"en-gb", 0x2e}, /* Great Britain (UK5.kt) */ + {"ko", 0x2f}, /* Korea (Korea5.kt) */ + {"tw", 0x30}, /* Taiwan (Taiwan5.kt) */ + {"ja", 0x31}, /* Japan (Japan5.kt) */ + {"fr-ca", 0x32}, /* Canada/French (Canada_Fr5.kt) */ + {"hu", 0x33}, /* Hungary (Hungary5.kt) */ + {"pl", 0x34}, /* Poland (Poland5.kt) */ + {"cz", 0x35}, /* Czech (Czech5.kt) */ + {"ru", 0x36}, /* Russia (Russia5.kt) */ + {"lv", 0x37}, /* Latvia (Latvia5.kt) */ + {"tr", 0x38}, /* Turkey-Q5 (TurkeyQ5.kt) */ + {"gr", 0x39}, /* Greece (Greece5.kt) */ + {"ar", 0x3a}, /* Arabic (Arabic5.kt) */ + {"lt", 0x3b}, /* Lithuania (Lithuania5.kt) */ + {"nl-be", 0x3c}, /* Belgium (Belgian5.kt) */ + {"be", 0x3c}, /* Belgium (Belgian5.kt) */ + }; + + for (i = 0; + i < sizeof(languages) / sizeof(struct layout_values); + i++) { + if (!strcmp(kbd_layout, languages[i].lang)) { + ret = languages[i].dip; + return ret; + } + } + + /* Found no known language code */ + if ((kbd_layout[0] >= '0') && (kbd_layout[0] <= '9')) { + unsigned int tmp; + + /* As a fallback we also accept numeric dip switch value */ + if (!qemu_strtoui(kbd_layout, NULL, 0, &tmp)) { + ret = tmp; + } + } + } + + if (ret == 0xff) { + /* Final fallback if keyboard_layout was not set or recognized */ + ret = 0x21; /* en-us layout */ + } + return ret; +} + static void handle_kbd_command(ESCCChannelState *s, int val) { trace_escc_kbd_command(val); @@ -867,7 +943,7 @@ static void handle_kbd_command(ESCCChannelState *s, int val) case 0xf: clear_queue(s); put_queue(s, 0xfe); - put_queue(s, 0x21); /* en-us layout */ + put_queue(s, sunkbd_layout_dip_switch(s->sunkbd_layout)); break; default: break; @@ -976,6 +1052,7 @@ static Property escc_properties[] = { DEFINE_PROP_UINT32("chnAtype", ESCCState, chn[1].type, 0), DEFINE_PROP_CHR("chrB", ESCCState, chn[0].chr), DEFINE_PROP_CHR("chrA", ESCCState, chn[1].chr), + DEFINE_PROP_STRING("chnA-sunkbd-layout", ESCCState, chn[1].sunkbd_layout), DEFINE_PROP_END_OF_LIST(), }; |