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; | ... | ... |