pbrook | cf0dbb2 | 2007-11-18 14:36:08 +0000 | [diff] [blame] | 1 | /* |
| 2 | * Gamepad style buttons connected to IRQ/GPIO lines |
| 3 | * |
| 4 | * Copyright (c) 2007 CodeSourcery. |
| 5 | * Written by Paul Brook |
| 6 | * |
Matthew Fernandez | 8e31bf3 | 2011-06-26 12:21:35 +1000 | [diff] [blame] | 7 | * This code is licensed under the GPL. |
pbrook | cf0dbb2 | 2007-11-18 14:36:08 +0000 | [diff] [blame] | 8 | */ |
Paolo Bonzini | 83c9f4c | 2013-02-04 15:40:22 +0100 | [diff] [blame] | 9 | #include "hw/hw.h" |
Peter Maydell | bd2be15 | 2013-04-09 15:26:55 +0100 | [diff] [blame] | 10 | #include "hw/devices.h" |
Paolo Bonzini | 28ecbae | 2012-11-28 12:06:30 +0100 | [diff] [blame] | 11 | #include "ui/console.h" |
pbrook | cf0dbb2 | 2007-11-18 14:36:08 +0000 | [diff] [blame] | 12 | |
| 13 | typedef struct { |
| 14 | qemu_irq irq; |
| 15 | int keycode; |
Juan Quintela | 4483c7a | 2010-12-02 02:36:38 +0100 | [diff] [blame] | 16 | uint8_t pressed; |
pbrook | cf0dbb2 | 2007-11-18 14:36:08 +0000 | [diff] [blame] | 17 | } gamepad_button; |
| 18 | |
| 19 | typedef struct { |
| 20 | gamepad_button *buttons; |
| 21 | int num_buttons; |
| 22 | int extension; |
| 23 | } gamepad_state; |
| 24 | |
| 25 | static void stellaris_gamepad_put_key(void * opaque, int keycode) |
| 26 | { |
| 27 | gamepad_state *s = (gamepad_state *)opaque; |
| 28 | int i; |
| 29 | int down; |
| 30 | |
| 31 | if (keycode == 0xe0 && !s->extension) { |
| 32 | s->extension = 0x80; |
| 33 | return; |
| 34 | } |
| 35 | |
| 36 | down = (keycode & 0x80) == 0; |
| 37 | keycode = (keycode & 0x7f) | s->extension; |
| 38 | |
| 39 | for (i = 0; i < s->num_buttons; i++) { |
| 40 | if (s->buttons[i].keycode == keycode |
| 41 | && s->buttons[i].pressed != down) { |
| 42 | s->buttons[i].pressed = down; |
| 43 | qemu_set_irq(s->buttons[i].irq, down); |
| 44 | } |
| 45 | } |
| 46 | |
| 47 | s->extension = 0; |
| 48 | } |
| 49 | |
Juan Quintela | 4483c7a | 2010-12-02 02:36:38 +0100 | [diff] [blame] | 50 | static const VMStateDescription vmstate_stellaris_button = { |
| 51 | .name = "stellaris_button", |
| 52 | .version_id = 0, |
| 53 | .minimum_version_id = 0, |
| 54 | .minimum_version_id_old = 0, |
| 55 | .fields = (VMStateField[]) { |
| 56 | VMSTATE_UINT8(pressed, gamepad_button), |
| 57 | VMSTATE_END_OF_LIST() |
| 58 | } |
| 59 | }; |
pbrook | 23e3929 | 2008-07-02 16:48:32 +0000 | [diff] [blame] | 60 | |
Juan Quintela | 4483c7a | 2010-12-02 02:36:38 +0100 | [diff] [blame] | 61 | static const VMStateDescription vmstate_stellaris_gamepad = { |
| 62 | .name = "stellaris_gamepad", |
| 63 | .version_id = 1, |
| 64 | .minimum_version_id = 1, |
| 65 | .minimum_version_id_old = 1, |
| 66 | .fields = (VMStateField[]) { |
| 67 | VMSTATE_INT32(extension, gamepad_state), |
| 68 | VMSTATE_STRUCT_VARRAY_INT32(buttons, gamepad_state, num_buttons, 0, |
| 69 | vmstate_stellaris_button, gamepad_button), |
| 70 | VMSTATE_END_OF_LIST() |
| 71 | } |
| 72 | }; |
pbrook | 23e3929 | 2008-07-02 16:48:32 +0000 | [diff] [blame] | 73 | |
pbrook | cf0dbb2 | 2007-11-18 14:36:08 +0000 | [diff] [blame] | 74 | /* Returns an array 5 ouput slots. */ |
| 75 | void stellaris_gamepad_init(int n, qemu_irq *irq, const int *keycode) |
| 76 | { |
| 77 | gamepad_state *s; |
| 78 | int i; |
| 79 | |
Anthony Liguori | 7267c09 | 2011-08-20 22:09:37 -0500 | [diff] [blame] | 80 | s = (gamepad_state *)g_malloc0(sizeof (gamepad_state)); |
| 81 | s->buttons = (gamepad_button *)g_malloc0(n * sizeof (gamepad_button)); |
pbrook | cf0dbb2 | 2007-11-18 14:36:08 +0000 | [diff] [blame] | 82 | for (i = 0; i < n; i++) { |
| 83 | s->buttons[i].irq = irq[i]; |
| 84 | s->buttons[i].keycode = keycode[i]; |
| 85 | } |
| 86 | s->num_buttons = n; |
| 87 | qemu_add_kbd_event_handler(stellaris_gamepad_put_key, s); |
Juan Quintela | 4483c7a | 2010-12-02 02:36:38 +0100 | [diff] [blame] | 88 | vmstate_register(NULL, -1, &vmstate_stellaris_gamepad, s); |
pbrook | cf0dbb2 | 2007-11-18 14:36:08 +0000 | [diff] [blame] | 89 | } |