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