xref: /qemu/hw/input/stellaris_gamepad.c (revision 281e461820db96a017ebf0fc36474d36feb33902)
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 } StellarisGamepadButton;
21 
22 typedef struct {
23     StellarisGamepadButton *buttons;
24     int num_buttons;
25     int extension;
26 } StellarisGamepad;
27 
28 static void stellaris_gamepad_put_key(void * opaque, int keycode)
29 {
30     StellarisGamepad *s = (StellarisGamepad *)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, StellarisGamepadButton),
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, StellarisGamepad),
69         VMSTATE_STRUCT_VARRAY_POINTER_INT32(buttons, StellarisGamepad,
70                                             num_buttons,
71                                             vmstate_stellaris_button,
72                                             StellarisGamepadButton),
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     StellarisGamepad *s;
81     int i;
82 
83     s = g_new0(StellarisGamepad, 1);
84     s->buttons = g_new0(StellarisGamepadButton, 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