hw/input/stellaris_input: Convert to qdev

Convert the hw/input/stellaris_input device to qdev.

The interface uses an array property for the board to specify the
keycodes to use, so the s->keycodes memory is now allocated by the
array-property machinery.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Tested-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Message-id: 20231030114802.3671871-6-peter.maydell@linaro.org
This commit is contained in:
Peter Maydell 2023-10-30 11:48:01 +00:00
parent 5f8d505e3a
commit a75f336b97
3 changed files with 87 additions and 32 deletions

View File

@ -31,6 +31,7 @@
#include "hw/timer/stellaris-gptm.h"
#include "hw/qdev-clock.h"
#include "qom/object.h"
#include "qapi/qmp/qlist.h"
#define GPIO_A 0
#define GPIO_B 1
@ -1274,16 +1275,27 @@ static void stellaris_init(MachineState *ms, stellaris_board_info *board)
sysbus_connect_irq(SYS_BUS_DEVICE(enet), 0, qdev_get_gpio_in(nvic, 42));
}
if (board->peripherals & BP_GAMEPAD) {
qemu_irq gpad_irq[5];
QList *gpad_keycode_list = qlist_new();
static const int gpad_keycode[5] = { 0xc8, 0xd0, 0xcb, 0xcd, 0x1d };
DeviceState *gpad;
gpad_irq[0] = qemu_irq_invert(gpio_in[GPIO_E][0]); /* up */
gpad_irq[1] = qemu_irq_invert(gpio_in[GPIO_E][1]); /* down */
gpad_irq[2] = qemu_irq_invert(gpio_in[GPIO_E][2]); /* left */
gpad_irq[3] = qemu_irq_invert(gpio_in[GPIO_E][3]); /* right */
gpad_irq[4] = qemu_irq_invert(gpio_in[GPIO_F][1]); /* select */
gpad = qdev_new(TYPE_STELLARIS_GAMEPAD);
for (i = 0; i < ARRAY_SIZE(gpad_keycode); i++) {
qlist_append_int(gpad_keycode_list, gpad_keycode[i]);
}
qdev_prop_set_array(gpad, "keycodes", gpad_keycode_list);
sysbus_realize_and_unref(SYS_BUS_DEVICE(gpad), &error_fatal);
stellaris_gamepad_init(5, gpad_irq, gpad_keycode);
qdev_connect_gpio_out(gpad, 0,
qemu_irq_invert(gpio_in[GPIO_E][0])); /* up */
qdev_connect_gpio_out(gpad, 1,
qemu_irq_invert(gpio_in[GPIO_E][1])); /* down */
qdev_connect_gpio_out(gpad, 2,
qemu_irq_invert(gpio_in[GPIO_E][2])); /* left */
qdev_connect_gpio_out(gpad, 3,
qemu_irq_invert(gpio_in[GPIO_E][3])); /* right */
qdev_connect_gpio_out(gpad, 4,
qemu_irq_invert(gpio_in[GPIO_F][1])); /* select */
}
for (i = 0; i < 7; i++) {
if (board->dc4 & (1 << i)) {

View File

@ -8,19 +8,13 @@
*/
#include "qemu/osdep.h"
#include "qapi/error.h"
#include "hw/input/stellaris_gamepad.h"
#include "hw/irq.h"
#include "hw/qdev-properties.h"
#include "migration/vmstate.h"
#include "ui/console.h"
typedef struct {
uint32_t num_buttons;
int extension;
qemu_irq *irqs;
uint32_t *keycodes;
uint8_t *pressed;
} StellarisGamepad;
static void stellaris_gamepad_put_key(void * opaque, int keycode)
{
StellarisGamepad *s = (StellarisGamepad *)opaque;
@ -57,22 +51,52 @@ static const VMStateDescription vmstate_stellaris_gamepad = {
}
};
/* Returns an array of 5 output slots. */
void stellaris_gamepad_init(int n, qemu_irq *irq, const int *keycode)
static void stellaris_gamepad_realize(DeviceState *dev, Error **errp)
{
StellarisGamepad *s;
int i;
StellarisGamepad *s = STELLARIS_GAMEPAD(dev);
s = g_new0(StellarisGamepad, 1);
s->irqs = g_new0(qemu_irq, n);
s->keycodes = g_new0(uint32_t, n);
s->pressed = g_new0(uint8_t, n);
for (i = 0; i < n; i++) {
s->irqs[i] = irq[i];
s->keycodes[i] = keycode[i];
if (s->num_buttons == 0) {
error_setg(errp, "keycodes property array must be set");
return;
}
s->num_buttons = n;
qemu_add_kbd_event_handler(stellaris_gamepad_put_key, s);
vmstate_register(NULL, VMSTATE_INSTANCE_ID_ANY,
&vmstate_stellaris_gamepad, s);
s->irqs = g_new0(qemu_irq, s->num_buttons);
s->pressed = g_new0(uint8_t, s->num_buttons);
qdev_init_gpio_out(dev, s->irqs, s->num_buttons);
qemu_add_kbd_event_handler(stellaris_gamepad_put_key, dev);
}
static void stellaris_gamepad_reset_enter(Object *obj, ResetType type)
{
StellarisGamepad *s = STELLARIS_GAMEPAD(obj);
memset(s->pressed, 0, s->num_buttons * sizeof(uint8_t));
}
static Property stellaris_gamepad_properties[] = {
DEFINE_PROP_ARRAY("keycodes", StellarisGamepad, num_buttons,
keycodes, qdev_prop_uint32, uint32_t),
DEFINE_PROP_END_OF_LIST(),
};
static void stellaris_gamepad_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
ResettableClass *rc = RESETTABLE_CLASS(klass);
rc->phases.enter = stellaris_gamepad_reset_enter;
dc->realize = stellaris_gamepad_realize;
dc->vmsd = &vmstate_stellaris_gamepad;
device_class_set_props(dc, stellaris_gamepad_properties);
}
static const TypeInfo stellaris_gamepad_info[] = {
{
.name = TYPE_STELLARIS_GAMEPAD,
.parent = TYPE_SYS_BUS_DEVICE,
.instance_size = sizeof(StellarisGamepad),
.class_init = stellaris_gamepad_class_init,
},
};
DEFINE_TYPES(stellaris_gamepad_info);

View File

@ -11,8 +11,27 @@
#ifndef HW_INPUT_STELLARIS_GAMEPAD_H
#define HW_INPUT_STELLARIS_GAMEPAD_H
#include "hw/sysbus.h"
#include "qom/object.h"
/* stellaris_gamepad.c */
void stellaris_gamepad_init(int n, qemu_irq *irq, const int *keycode);
/*
* QEMU interface:
* + QOM array property "keycodes": uint32_t QEMU keycodes to handle
* + unnamed GPIO outputs: one per keycode, in the same order as the
* "keycodes" array property entries; asserted when key is down
*/
#define TYPE_STELLARIS_GAMEPAD "stellaris-gamepad"
OBJECT_DECLARE_SIMPLE_TYPE(StellarisGamepad, STELLARIS_GAMEPAD)
struct StellarisGamepad {
SysBusDevice parent_obj;
uint32_t num_buttons;
qemu_irq *irqs;
uint32_t *keycodes;
uint8_t *pressed;
int extension;
};
#endif