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