xref: /qemu/hw/input/stellaris_gamepad.c (revision c45460decbda7f94d188d2e18ead91b7c60d4e24)
1 /*
2  * Gamepad style buttons connected to IRQ/GPIO lines
3  *
4  * Copyright (c) 2007 CodeSourcery.
5  * Written by Paul Brook
6  *
7  * This code is licensed under the GPL.
8  */
9 
10 #include "qemu/osdep.h"
11 #include "hw/input/stellaris_gamepad.h"
12 #include "hw/irq.h"
13 #include "migration/vmstate.h"
14 #include "ui/console.h"
15 
16 typedef struct {
17     qemu_irq irq;
18     int keycode;
19     uint8_t pressed;
20 } gamepad_button;
21 
22 typedef struct {
23     gamepad_button *buttons;
24     int num_buttons;
25     int extension;
26 } gamepad_state;
27 
28 static void stellaris_gamepad_put_key(void * opaque, int keycode)
29 {
30     gamepad_state *s = (gamepad_state *)opaque;
31     int i;
32     int down;
33 
34     if (keycode == 0xe0 && !s->extension) {
35         s->extension = 0x80;
36         return;
37     }
38 
39     down = (keycode & 0x80) == 0;
40     keycode = (keycode & 0x7f) | s->extension;
41 
42     for (i = 0; i < s->num_buttons; i++) {
43         if (s->buttons[i].keycode == keycode
44                 && s->buttons[i].pressed != down) {
45             s->buttons[i].pressed = down;
46             qemu_set_irq(s->buttons[i].irq, down);
47         }
48     }
49 
50     s->extension = 0;
51 }
52 
53 static const VMStateDescription vmstate_stellaris_button = {
54     .name = "stellaris_button",
55     .version_id = 0,
56     .minimum_version_id = 0,
57     .fields = (VMStateField[]) {
58         VMSTATE_UINT8(pressed, gamepad_button),
59         VMSTATE_END_OF_LIST()
60     }
61 };
62 
63 static const VMStateDescription vmstate_stellaris_gamepad = {
64     .name = "stellaris_gamepad",
65     .version_id = 2,
66     .minimum_version_id = 2,
67     .fields = (VMStateField[]) {
68         VMSTATE_INT32(extension, gamepad_state),
69         VMSTATE_STRUCT_VARRAY_POINTER_INT32(buttons, gamepad_state,
70                                             num_buttons,
71                                             vmstate_stellaris_button,
72                                             gamepad_button),
73         VMSTATE_END_OF_LIST()
74     }
75 };
76 
77 /* Returns an array of 5 output slots.  */
78 void stellaris_gamepad_init(int n, qemu_irq *irq, const int *keycode)
79 {
80     gamepad_state *s;
81     int i;
82 
83     s = g_new0(gamepad_state, 1);
84     s->buttons = g_new0(gamepad_button, n);
85     for (i = 0; i < n; i++) {
86         s->buttons[i].irq = irq[i];
87         s->buttons[i].keycode = keycode[i];
88     }
89     s->num_buttons = n;
90     qemu_add_kbd_event_handler(stellaris_gamepad_put_key, s);
91     vmstate_register(NULL, VMSTATE_INSTANCE_ID_ANY,
92                      &vmstate_stellaris_gamepad, s);
93 }
94