xref: /qemu/hw/input/stellaris_gamepad.c (revision 06b40d250ecfa1633209c2e431a7a38acfd03a98)
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 "qapi/error.h"
12  #include "hw/input/stellaris_gamepad.h"
13  #include "hw/irq.h"
14  #include "hw/qdev-properties.h"
15  #include "migration/vmstate.h"
16  #include "ui/console.h"
17  
18  static void stellaris_gamepad_event(DeviceState *dev, QemuConsole *src,
19                                      InputEvent *evt)
20  {
21      StellarisGamepad *s = STELLARIS_GAMEPAD(dev);
22      InputKeyEvent *key = evt->u.key.data;
23      int qcode = qemu_input_key_value_to_qcode(key->key);
24      int i;
25  
26      for (i = 0; i < s->num_buttons; i++) {
27          if (s->keycodes[i] == qcode && s->pressed[i] != key->down) {
28              s->pressed[i] = key->down;
29              qemu_set_irq(s->irqs[i], key->down);
30          }
31      }
32  }
33  
34  static const VMStateDescription vmstate_stellaris_gamepad = {
35      .name = "stellaris_gamepad",
36      .version_id = 4,
37      .minimum_version_id = 4,
38      .fields = (const VMStateField[]) {
39          VMSTATE_VARRAY_UINT32(pressed, StellarisGamepad, num_buttons,
40                                0, vmstate_info_uint8, uint8_t),
41          VMSTATE_END_OF_LIST()
42      }
43  };
44  
45  static const QemuInputHandler stellaris_gamepad_handler = {
46      .name = "Stellaris Gamepad",
47      .mask = INPUT_EVENT_MASK_KEY,
48      .event = stellaris_gamepad_event,
49  };
50  
51  static void stellaris_gamepad_realize(DeviceState *dev, Error **errp)
52  {
53      StellarisGamepad *s = STELLARIS_GAMEPAD(dev);
54  
55      if (s->num_buttons == 0) {
56          error_setg(errp, "keycodes property array must be set");
57          return;
58      }
59  
60      s->irqs = g_new0(qemu_irq, s->num_buttons);
61      s->pressed = g_new0(uint8_t, s->num_buttons);
62      qdev_init_gpio_out(dev, s->irqs, s->num_buttons);
63      qemu_input_handler_register(dev, &stellaris_gamepad_handler);
64  }
65  
66  static void stellaris_gamepad_finalize(Object *obj)
67  {
68      StellarisGamepad *s = STELLARIS_GAMEPAD(obj);
69  
70      g_free(s->keycodes);
71  }
72  
73  static void stellaris_gamepad_reset_enter(Object *obj, ResetType type)
74  {
75      StellarisGamepad *s = STELLARIS_GAMEPAD(obj);
76  
77      memset(s->pressed, 0, s->num_buttons * sizeof(uint8_t));
78  }
79  
80  static const Property stellaris_gamepad_properties[] = {
81      DEFINE_PROP_ARRAY("keycodes", StellarisGamepad, num_buttons,
82                        keycodes, qdev_prop_uint32, uint32_t),
83  };
84  
85  static void stellaris_gamepad_class_init(ObjectClass *klass, const void *data)
86  {
87      DeviceClass *dc = DEVICE_CLASS(klass);
88      ResettableClass *rc = RESETTABLE_CLASS(klass);
89  
90      rc->phases.enter = stellaris_gamepad_reset_enter;
91      dc->realize = stellaris_gamepad_realize;
92      dc->vmsd = &vmstate_stellaris_gamepad;
93      device_class_set_props(dc, stellaris_gamepad_properties);
94  }
95  
96  static const TypeInfo stellaris_gamepad_info[] = {
97      {
98          .name = TYPE_STELLARIS_GAMEPAD,
99          .parent = TYPE_SYS_BUS_DEVICE,
100          .instance_size = sizeof(StellarisGamepad),
101          .instance_finalize = stellaris_gamepad_finalize,
102          .class_init = stellaris_gamepad_class_init,
103      },
104  };
105  
106  DEFINE_TYPES(stellaris_gamepad_info);
107