Commit 43febf49523552ca678eacc2677d3bac58cda4c0
1 parent
9706285b
Improve keyboard handling
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@3204 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
1 changed file
with
34 additions
and
3 deletions
hw/slavio_serial.c
@@ -95,6 +95,7 @@ typedef struct ChannelState { | @@ -95,6 +95,7 @@ typedef struct ChannelState { | ||
95 | uint8_t rx, tx, wregs[16], rregs[16]; | 95 | uint8_t rx, tx, wregs[16], rregs[16]; |
96 | SERIOQueue queue; | 96 | SERIOQueue queue; |
97 | CharDriverState *chr; | 97 | CharDriverState *chr; |
98 | + int e0_mode, led_mode; | ||
98 | } ChannelState; | 99 | } ChannelState; |
99 | 100 | ||
100 | struct SerialState { | 101 | struct SerialState { |
@@ -194,6 +195,7 @@ static void slavio_serial_reset_chn(ChannelState *s) | @@ -194,6 +195,7 @@ static void slavio_serial_reset_chn(ChannelState *s) | ||
194 | s->rx = s->tx = 0; | 195 | s->rx = s->tx = 0; |
195 | s->rxint = s->txint = 0; | 196 | s->rxint = s->txint = 0; |
196 | s->rxint_under_svc = s->txint_under_svc = 0; | 197 | s->rxint_under_svc = s->txint_under_svc = 0; |
198 | + s->e0_mode = s->led_mode = 0; | ||
197 | clear_queue(s); | 199 | clear_queue(s); |
198 | } | 200 | } |
199 | 201 | ||
@@ -632,30 +634,59 @@ static const uint8_t keycodes[128] = { | @@ -632,30 +634,59 @@ static const uint8_t keycodes[128] = { | ||
632 | 0, 45, 2, 4, 48, 0, 0, 21, 0, 0, 0, 0, 0, 120, 122, 67, | 634 | 0, 45, 2, 4, 48, 0, 0, 21, 0, 0, 0, 0, 0, 120, 122, 67, |
633 | }; | 635 | }; |
634 | 636 | ||
637 | +static const uint8_t e0_keycodes[128] = { | ||
638 | + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | ||
639 | + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 90, 76, 0, 0, | ||
640 | + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | ||
641 | + 0, 0, 0, 0, 0, 109, 0, 0, 13, 0, 0, 0, 0, 0, 0, 0, | ||
642 | + 0, 0, 0, 0, 0, 0, 0, 68, 69, 70, 0, 91, 0, 93, 0, 112, | ||
643 | + 113, 114, 94, 50, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | ||
644 | + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | ||
645 | + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | ||
646 | +}; | ||
647 | + | ||
635 | static void sunkbd_event(void *opaque, int ch) | 648 | static void sunkbd_event(void *opaque, int ch) |
636 | { | 649 | { |
637 | ChannelState *s = opaque; | 650 | ChannelState *s = opaque; |
638 | int release = ch & 0x80; | 651 | int release = ch & 0x80; |
639 | 652 | ||
640 | - ch = keycodes[ch & 0x7f]; | ||
641 | - KBD_DPRINTF("Keycode %d (%s)\n", ch, release? "release" : "press"); | 653 | + KBD_DPRINTF("Untranslated keycode %2.2x (%s)\n", ch, release? "release" : "press"); |
654 | + if (ch == 0xe0) { | ||
655 | + s->e0_mode = 1; | ||
656 | + return; | ||
657 | + } | ||
658 | + if (s->e0_mode) { | ||
659 | + s->e0_mode = 0; | ||
660 | + ch = e0_keycodes[ch & 0x7f]; | ||
661 | + } else { | ||
662 | + ch = keycodes[ch & 0x7f]; | ||
663 | + } | ||
664 | + KBD_DPRINTF("Translated keycode %2.2x\n", ch); | ||
642 | put_queue(s, ch | release); | 665 | put_queue(s, ch | release); |
643 | } | 666 | } |
644 | 667 | ||
645 | static void handle_kbd_command(ChannelState *s, int val) | 668 | static void handle_kbd_command(ChannelState *s, int val) |
646 | { | 669 | { |
647 | KBD_DPRINTF("Command %d\n", val); | 670 | KBD_DPRINTF("Command %d\n", val); |
671 | + if (s->led_mode) { // Ignore led byte | ||
672 | + s->led_mode = 0; | ||
673 | + return; | ||
674 | + } | ||
648 | switch (val) { | 675 | switch (val) { |
649 | case 1: // Reset, return type code | 676 | case 1: // Reset, return type code |
650 | clear_queue(s); | 677 | clear_queue(s); |
651 | put_queue(s, 0xff); | 678 | put_queue(s, 0xff); |
652 | put_queue(s, 4); // Type 4 | 679 | put_queue(s, 4); // Type 4 |
680 | + put_queue(s, 0x7f); | ||
653 | break; | 681 | break; |
682 | + case 0xe: // Set leds | ||
683 | + s->led_mode = 1; | ||
684 | + break; | ||
654 | case 7: // Query layout | 685 | case 7: // Query layout |
655 | case 0xf: | 686 | case 0xf: |
656 | clear_queue(s); | 687 | clear_queue(s); |
657 | put_queue(s, 0xfe); | 688 | put_queue(s, 0xfe); |
658 | - put_queue(s, 19); // XXX, layout? | 689 | + put_queue(s, 0); // XXX, layout? |
659 | break; | 690 | break; |
660 | default: | 691 | default: |
661 | break; | 692 | break; |