xref: /qemu/hw/input/stellaris_gamepad.c (revision c45460decbda7f94d188d2e18ead91b7c60d4e24)
1cf0dbb21Spbrook /*
2cf0dbb21Spbrook  * Gamepad style buttons connected to IRQ/GPIO lines
3cf0dbb21Spbrook  *
4cf0dbb21Spbrook  * Copyright (c) 2007 CodeSourcery.
5cf0dbb21Spbrook  * Written by Paul Brook
6cf0dbb21Spbrook  *
78e31bf38SMatthew Fernandez  * This code is licensed under the GPL.
8cf0dbb21Spbrook  */
964552b6bSMarkus Armbruster 
108ef94f0bSPeter Maydell #include "qemu/osdep.h"
11*c45460deSPeter Maydell #include "hw/input/stellaris_gamepad.h"
1264552b6bSMarkus Armbruster #include "hw/irq.h"
13d6454270SMarkus Armbruster #include "migration/vmstate.h"
1428ecbaeeSPaolo Bonzini #include "ui/console.h"
15cf0dbb21Spbrook 
16cf0dbb21Spbrook typedef struct {
17cf0dbb21Spbrook     qemu_irq irq;
18cf0dbb21Spbrook     int keycode;
194483c7acSJuan Quintela     uint8_t pressed;
20cf0dbb21Spbrook } gamepad_button;
21cf0dbb21Spbrook 
22cf0dbb21Spbrook typedef struct {
23cf0dbb21Spbrook     gamepad_button *buttons;
24cf0dbb21Spbrook     int num_buttons;
25cf0dbb21Spbrook     int extension;
26cf0dbb21Spbrook } gamepad_state;
27cf0dbb21Spbrook 
28cf0dbb21Spbrook static void stellaris_gamepad_put_key(void * opaque, int keycode)
29cf0dbb21Spbrook {
30cf0dbb21Spbrook     gamepad_state *s = (gamepad_state *)opaque;
31cf0dbb21Spbrook     int i;
32cf0dbb21Spbrook     int down;
33cf0dbb21Spbrook 
34cf0dbb21Spbrook     if (keycode == 0xe0 && !s->extension) {
35cf0dbb21Spbrook         s->extension = 0x80;
36cf0dbb21Spbrook         return;
37cf0dbb21Spbrook     }
38cf0dbb21Spbrook 
39cf0dbb21Spbrook     down = (keycode & 0x80) == 0;
40cf0dbb21Spbrook     keycode = (keycode & 0x7f) | s->extension;
41cf0dbb21Spbrook 
42cf0dbb21Spbrook     for (i = 0; i < s->num_buttons; i++) {
43cf0dbb21Spbrook         if (s->buttons[i].keycode == keycode
44cf0dbb21Spbrook                 && s->buttons[i].pressed != down) {
45cf0dbb21Spbrook             s->buttons[i].pressed = down;
46cf0dbb21Spbrook             qemu_set_irq(s->buttons[i].irq, down);
47cf0dbb21Spbrook         }
48cf0dbb21Spbrook     }
49cf0dbb21Spbrook 
50cf0dbb21Spbrook     s->extension = 0;
51cf0dbb21Spbrook }
52cf0dbb21Spbrook 
534483c7acSJuan Quintela static const VMStateDescription vmstate_stellaris_button = {
544483c7acSJuan Quintela     .name = "stellaris_button",
554483c7acSJuan Quintela     .version_id = 0,
564483c7acSJuan Quintela     .minimum_version_id = 0,
574483c7acSJuan Quintela     .fields = (VMStateField[]) {
584483c7acSJuan Quintela         VMSTATE_UINT8(pressed, gamepad_button),
594483c7acSJuan Quintela         VMSTATE_END_OF_LIST()
6023e39294Spbrook     }
614483c7acSJuan Quintela };
6223e39294Spbrook 
634483c7acSJuan Quintela static const VMStateDescription vmstate_stellaris_gamepad = {
644483c7acSJuan Quintela     .name = "stellaris_gamepad",
65372e458eSPeter Maydell     .version_id = 2,
66372e458eSPeter Maydell     .minimum_version_id = 2,
674483c7acSJuan Quintela     .fields = (VMStateField[]) {
684483c7acSJuan Quintela         VMSTATE_INT32(extension, gamepad_state),
69372e458eSPeter Maydell         VMSTATE_STRUCT_VARRAY_POINTER_INT32(buttons, gamepad_state,
70372e458eSPeter Maydell                                             num_buttons,
71372e458eSPeter Maydell                                             vmstate_stellaris_button,
72372e458eSPeter Maydell                                             gamepad_button),
734483c7acSJuan Quintela         VMSTATE_END_OF_LIST()
7423e39294Spbrook     }
754483c7acSJuan Quintela };
7623e39294Spbrook 
7767cc32ebSVeres Lajos /* Returns an array of 5 output slots.  */
78cf0dbb21Spbrook void stellaris_gamepad_init(int n, qemu_irq *irq, const int *keycode)
79cf0dbb21Spbrook {
80cf0dbb21Spbrook     gamepad_state *s;
81cf0dbb21Spbrook     int i;
82cf0dbb21Spbrook 
83b45c03f5SMarkus Armbruster     s = g_new0(gamepad_state, 1);
84b45c03f5SMarkus Armbruster     s->buttons = g_new0(gamepad_button, n);
85cf0dbb21Spbrook     for (i = 0; i < n; i++) {
86cf0dbb21Spbrook         s->buttons[i].irq = irq[i];
87cf0dbb21Spbrook         s->buttons[i].keycode = keycode[i];
88cf0dbb21Spbrook     }
89cf0dbb21Spbrook     s->num_buttons = n;
90cf0dbb21Spbrook     qemu_add_kbd_event_handler(stellaris_gamepad_put_key, s);
911df2c9a2SPeter Xu     vmstate_register(NULL, VMSTATE_INSTANCE_ID_ANY,
921df2c9a2SPeter Xu                      &vmstate_stellaris_gamepad, s);
93cf0dbb21Spbrook }
94