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 | 95 | uint8_t rx, tx, wregs[16], rregs[16]; |
96 | 96 | SERIOQueue queue; |
97 | 97 | CharDriverState *chr; |
98 | + int e0_mode, led_mode; | |
98 | 99 | } ChannelState; |
99 | 100 | |
100 | 101 | struct SerialState { |
... | ... | @@ -194,6 +195,7 @@ static void slavio_serial_reset_chn(ChannelState *s) |
194 | 195 | s->rx = s->tx = 0; |
195 | 196 | s->rxint = s->txint = 0; |
196 | 197 | s->rxint_under_svc = s->txint_under_svc = 0; |
198 | + s->e0_mode = s->led_mode = 0; | |
197 | 199 | clear_queue(s); |
198 | 200 | } |
199 | 201 | |
... | ... | @@ -632,30 +634,59 @@ static const uint8_t keycodes[128] = { |
632 | 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 | 648 | static void sunkbd_event(void *opaque, int ch) |
636 | 649 | { |
637 | 650 | ChannelState *s = opaque; |
638 | 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 | 665 | put_queue(s, ch | release); |
643 | 666 | } |
644 | 667 | |
645 | 668 | static void handle_kbd_command(ChannelState *s, int val) |
646 | 669 | { |
647 | 670 | KBD_DPRINTF("Command %d\n", val); |
671 | + if (s->led_mode) { // Ignore led byte | |
672 | + s->led_mode = 0; | |
673 | + return; | |
674 | + } | |
648 | 675 | switch (val) { |
649 | 676 | case 1: // Reset, return type code |
650 | 677 | clear_queue(s); |
651 | 678 | put_queue(s, 0xff); |
652 | 679 | put_queue(s, 4); // Type 4 |
680 | + put_queue(s, 0x7f); | |
653 | 681 | break; |
682 | + case 0xe: // Set leds | |
683 | + s->led_mode = 1; | |
684 | + break; | |
654 | 685 | case 7: // Query layout |
655 | 686 | case 0xf: |
656 | 687 | clear_queue(s); |
657 | 688 | put_queue(s, 0xfe); |
658 | - put_queue(s, 19); // XXX, layout? | |
689 | + put_queue(s, 0); // XXX, layout? | |
659 | 690 | break; |
660 | 691 | default: |
661 | 692 | break; | ... | ... |