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" 11a75f336bSPeter Maydell #include "qapi/error.h" 12c45460deSPeter Maydell #include "hw/input/stellaris_gamepad.h" 13c45460deSPeter Maydell #include "hw/irq.h" 14a75f336bSPeter Maydell #include "hw/qdev-properties.h" 15c45460deSPeter Maydell #include "migration/vmstate.h" 16c45460deSPeter Maydell #include "ui/console.h" 17c45460deSPeter Maydell 187c76f397SPeter Maydell static void stellaris_gamepad_event(DeviceState *dev, QemuConsole *src, 197c76f397SPeter Maydell InputEvent *evt) 20c45460deSPeter Maydell { 217c76f397SPeter Maydell StellarisGamepad *s = STELLARIS_GAMEPAD(dev); 227c76f397SPeter Maydell InputKeyEvent *key = evt->u.key.data; 237c76f397SPeter Maydell int qcode = qemu_input_key_value_to_qcode(key->key); 24c45460deSPeter Maydell int i; 25c45460deSPeter Maydell 26c45460deSPeter Maydell for (i = 0; i < s->num_buttons; i++) { 277c76f397SPeter Maydell if (s->keycodes[i] == qcode && s->pressed[i] != key->down) { 287c76f397SPeter Maydell s->pressed[i] = key->down; 297c76f397SPeter Maydell qemu_set_irq(s->irqs[i], key->down); 30c45460deSPeter Maydell } 31c45460deSPeter Maydell } 32c45460deSPeter Maydell } 33c45460deSPeter Maydell 34c45460deSPeter Maydell static const VMStateDescription vmstate_stellaris_gamepad = { 35c45460deSPeter Maydell .name = "stellaris_gamepad", 367c76f397SPeter Maydell .version_id = 4, 377c76f397SPeter Maydell .minimum_version_id = 4, 38c45460deSPeter Maydell .fields = (VMStateField[]) { 395f8d505eSPeter Maydell VMSTATE_VARRAY_UINT32(pressed, StellarisGamepad, num_buttons, 405f8d505eSPeter Maydell 0, vmstate_info_uint8, uint8_t), 41c45460deSPeter Maydell VMSTATE_END_OF_LIST() 42c45460deSPeter Maydell } 43c45460deSPeter Maydell }; 44c45460deSPeter Maydell 457c76f397SPeter Maydell static const QemuInputHandler stellaris_gamepad_handler = { 467c76f397SPeter Maydell .name = "Stellaris Gamepad", 477c76f397SPeter Maydell .mask = INPUT_EVENT_MASK_KEY, 487c76f397SPeter Maydell .event = stellaris_gamepad_event, 497c76f397SPeter Maydell }; 507c76f397SPeter Maydell 51a75f336bSPeter Maydell static void stellaris_gamepad_realize(DeviceState *dev, Error **errp) 52c45460deSPeter Maydell { 53a75f336bSPeter Maydell StellarisGamepad *s = STELLARIS_GAMEPAD(dev); 54c45460deSPeter Maydell 55a75f336bSPeter Maydell if (s->num_buttons == 0) { 56a75f336bSPeter Maydell error_setg(errp, "keycodes property array must be set"); 57a75f336bSPeter Maydell return; 58c45460deSPeter Maydell } 59a75f336bSPeter Maydell 60a75f336bSPeter Maydell s->irqs = g_new0(qemu_irq, s->num_buttons); 61a75f336bSPeter Maydell s->pressed = g_new0(uint8_t, s->num_buttons); 62a75f336bSPeter Maydell qdev_init_gpio_out(dev, s->irqs, s->num_buttons); 637c76f397SPeter Maydell qemu_input_handler_register(dev, &stellaris_gamepad_handler); 64c45460deSPeter Maydell } 65a75f336bSPeter Maydell 66*6e782ffdSPhilippe Mathieu-Daudé static void stellaris_gamepad_finalize(Object *obj) 67*6e782ffdSPhilippe Mathieu-Daudé { 68*6e782ffdSPhilippe Mathieu-Daudé StellarisGamepad *s = STELLARIS_GAMEPAD(obj); 69*6e782ffdSPhilippe Mathieu-Daudé 70*6e782ffdSPhilippe Mathieu-Daudé g_free(s->keycodes); 71*6e782ffdSPhilippe Mathieu-Daudé } 72*6e782ffdSPhilippe Mathieu-Daudé 73a75f336bSPeter Maydell static void stellaris_gamepad_reset_enter(Object *obj, ResetType type) 74a75f336bSPeter Maydell { 75a75f336bSPeter Maydell StellarisGamepad *s = STELLARIS_GAMEPAD(obj); 76a75f336bSPeter Maydell 77a75f336bSPeter Maydell memset(s->pressed, 0, s->num_buttons * sizeof(uint8_t)); 78a75f336bSPeter Maydell } 79a75f336bSPeter Maydell 80a75f336bSPeter Maydell static Property stellaris_gamepad_properties[] = { 81a75f336bSPeter Maydell DEFINE_PROP_ARRAY("keycodes", StellarisGamepad, num_buttons, 82a75f336bSPeter Maydell keycodes, qdev_prop_uint32, uint32_t), 83a75f336bSPeter Maydell DEFINE_PROP_END_OF_LIST(), 84a75f336bSPeter Maydell }; 85a75f336bSPeter Maydell 86a75f336bSPeter Maydell static void stellaris_gamepad_class_init(ObjectClass *klass, void *data) 87a75f336bSPeter Maydell { 88a75f336bSPeter Maydell DeviceClass *dc = DEVICE_CLASS(klass); 89a75f336bSPeter Maydell ResettableClass *rc = RESETTABLE_CLASS(klass); 90a75f336bSPeter Maydell 91a75f336bSPeter Maydell rc->phases.enter = stellaris_gamepad_reset_enter; 92a75f336bSPeter Maydell dc->realize = stellaris_gamepad_realize; 93a75f336bSPeter Maydell dc->vmsd = &vmstate_stellaris_gamepad; 94a75f336bSPeter Maydell device_class_set_props(dc, stellaris_gamepad_properties); 95a75f336bSPeter Maydell } 96a75f336bSPeter Maydell 97a75f336bSPeter Maydell static const TypeInfo stellaris_gamepad_info[] = { 98a75f336bSPeter Maydell { 99a75f336bSPeter Maydell .name = TYPE_STELLARIS_GAMEPAD, 100a75f336bSPeter Maydell .parent = TYPE_SYS_BUS_DEVICE, 101a75f336bSPeter Maydell .instance_size = sizeof(StellarisGamepad), 102*6e782ffdSPhilippe Mathieu-Daudé .instance_finalize = stellaris_gamepad_finalize, 103a75f336bSPeter Maydell .class_init = stellaris_gamepad_class_init, 104a75f336bSPeter Maydell }, 105a75f336bSPeter Maydell }; 106a75f336bSPeter Maydell 107a75f336bSPeter Maydell DEFINE_TYPES(stellaris_gamepad_info); 108