xref: /openbmc/qemu/hw/input/stellaris_gamepad.c (revision a75f336b97a643fc536ba847042f840890e9b378)
1c45460deSPeter Maydell /*
2c45460deSPeter Maydell  * Gamepad style buttons connected to IRQ/GPIO lines
3c45460deSPeter Maydell  *
4c45460deSPeter Maydell  * Copyright (c) 2007 CodeSourcery.
5c45460deSPeter Maydell  * Written by Paul Brook
6c45460deSPeter Maydell  *
7c45460deSPeter Maydell  * This code is licensed under the GPL.
8c45460deSPeter Maydell  */
9c45460deSPeter Maydell 
10c45460deSPeter Maydell #include "qemu/osdep.h"
11*a75f336bSPeter Maydell #include "qapi/error.h"
12c45460deSPeter Maydell #include "hw/input/stellaris_gamepad.h"
13c45460deSPeter Maydell #include "hw/irq.h"
14*a75f336bSPeter Maydell #include "hw/qdev-properties.h"
15c45460deSPeter Maydell #include "migration/vmstate.h"
16c45460deSPeter Maydell #include "ui/console.h"
17c45460deSPeter Maydell 
18c45460deSPeter Maydell static void stellaris_gamepad_put_key(void * opaque, int keycode)
19c45460deSPeter Maydell {
20281e4618SPeter Maydell     StellarisGamepad *s = (StellarisGamepad *)opaque;
21c45460deSPeter Maydell     int i;
22c45460deSPeter Maydell     int down;
23c45460deSPeter Maydell 
24c45460deSPeter Maydell     if (keycode == 0xe0 && !s->extension) {
25c45460deSPeter Maydell         s->extension = 0x80;
26c45460deSPeter Maydell         return;
27c45460deSPeter Maydell     }
28c45460deSPeter Maydell 
29c45460deSPeter Maydell     down = (keycode & 0x80) == 0;
30c45460deSPeter Maydell     keycode = (keycode & 0x7f) | s->extension;
31c45460deSPeter Maydell 
32c45460deSPeter Maydell     for (i = 0; i < s->num_buttons; i++) {
335f8d505eSPeter Maydell         if (s->keycodes[i] == keycode && s->pressed[i] != down) {
345f8d505eSPeter Maydell             s->pressed[i] = down;
355f8d505eSPeter Maydell             qemu_set_irq(s->irqs[i], down);
36c45460deSPeter Maydell         }
37c45460deSPeter Maydell     }
38c45460deSPeter Maydell 
39c45460deSPeter Maydell     s->extension = 0;
40c45460deSPeter Maydell }
41c45460deSPeter Maydell 
42c45460deSPeter Maydell static const VMStateDescription vmstate_stellaris_gamepad = {
43c45460deSPeter Maydell     .name = "stellaris_gamepad",
445f8d505eSPeter Maydell     .version_id = 3,
455f8d505eSPeter Maydell     .minimum_version_id = 3,
46c45460deSPeter Maydell     .fields = (VMStateField[]) {
47281e4618SPeter Maydell         VMSTATE_INT32(extension, StellarisGamepad),
485f8d505eSPeter Maydell         VMSTATE_VARRAY_UINT32(pressed, StellarisGamepad, num_buttons,
495f8d505eSPeter Maydell                               0, vmstate_info_uint8, uint8_t),
50c45460deSPeter Maydell         VMSTATE_END_OF_LIST()
51c45460deSPeter Maydell     }
52c45460deSPeter Maydell };
53c45460deSPeter Maydell 
54*a75f336bSPeter Maydell static void stellaris_gamepad_realize(DeviceState *dev, Error **errp)
55c45460deSPeter Maydell {
56*a75f336bSPeter Maydell     StellarisGamepad *s = STELLARIS_GAMEPAD(dev);
57c45460deSPeter Maydell 
58*a75f336bSPeter Maydell     if (s->num_buttons == 0) {
59*a75f336bSPeter Maydell         error_setg(errp, "keycodes property array must be set");
60*a75f336bSPeter Maydell         return;
61c45460deSPeter Maydell     }
62*a75f336bSPeter Maydell 
63*a75f336bSPeter Maydell     s->irqs = g_new0(qemu_irq, s->num_buttons);
64*a75f336bSPeter Maydell     s->pressed = g_new0(uint8_t, s->num_buttons);
65*a75f336bSPeter Maydell     qdev_init_gpio_out(dev, s->irqs, s->num_buttons);
66*a75f336bSPeter Maydell     qemu_add_kbd_event_handler(stellaris_gamepad_put_key, dev);
67c45460deSPeter Maydell }
68*a75f336bSPeter Maydell 
69*a75f336bSPeter Maydell static void stellaris_gamepad_reset_enter(Object *obj, ResetType type)
70*a75f336bSPeter Maydell {
71*a75f336bSPeter Maydell     StellarisGamepad *s = STELLARIS_GAMEPAD(obj);
72*a75f336bSPeter Maydell 
73*a75f336bSPeter Maydell     memset(s->pressed, 0, s->num_buttons * sizeof(uint8_t));
74*a75f336bSPeter Maydell }
75*a75f336bSPeter Maydell 
76*a75f336bSPeter Maydell static Property stellaris_gamepad_properties[] = {
77*a75f336bSPeter Maydell     DEFINE_PROP_ARRAY("keycodes", StellarisGamepad, num_buttons,
78*a75f336bSPeter Maydell                       keycodes, qdev_prop_uint32, uint32_t),
79*a75f336bSPeter Maydell     DEFINE_PROP_END_OF_LIST(),
80*a75f336bSPeter Maydell };
81*a75f336bSPeter Maydell 
82*a75f336bSPeter Maydell static void stellaris_gamepad_class_init(ObjectClass *klass, void *data)
83*a75f336bSPeter Maydell {
84*a75f336bSPeter Maydell     DeviceClass *dc = DEVICE_CLASS(klass);
85*a75f336bSPeter Maydell     ResettableClass *rc = RESETTABLE_CLASS(klass);
86*a75f336bSPeter Maydell 
87*a75f336bSPeter Maydell     rc->phases.enter = stellaris_gamepad_reset_enter;
88*a75f336bSPeter Maydell     dc->realize = stellaris_gamepad_realize;
89*a75f336bSPeter Maydell     dc->vmsd = &vmstate_stellaris_gamepad;
90*a75f336bSPeter Maydell     device_class_set_props(dc, stellaris_gamepad_properties);
91*a75f336bSPeter Maydell }
92*a75f336bSPeter Maydell 
93*a75f336bSPeter Maydell static const TypeInfo stellaris_gamepad_info[] = {
94*a75f336bSPeter Maydell     {
95*a75f336bSPeter Maydell         .name = TYPE_STELLARIS_GAMEPAD,
96*a75f336bSPeter Maydell         .parent = TYPE_SYS_BUS_DEVICE,
97*a75f336bSPeter Maydell         .instance_size = sizeof(StellarisGamepad),
98*a75f336bSPeter Maydell         .class_init = stellaris_gamepad_class_init,
99*a75f336bSPeter Maydell     },
100*a75f336bSPeter Maydell };
101*a75f336bSPeter Maydell 
102*a75f336bSPeter Maydell DEFINE_TYPES(stellaris_gamepad_info);
103