Fix the size of the property fields.
[qemu/navara.git] / hw / gpio_rotary.c
blob9ccd157bb68faf5d6202b80c6a23da86e04386c1
1 /*
2 * GPIO Rotary Coder
4 * Copyright (c) 2009 Filip Navara
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to deal
8 * in the Software without restriction, including without limitation the rights
9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 * copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 * THE SOFTWARE.
25 #include "sysbus.h"
26 #include "console.h"
28 typedef struct RotaryCoderState {
29 SysBusDevice busdev;
30 qemu_irq out[2];
31 uint8_t state;
32 uint8_t extension;
33 uint32_t key_left;
34 uint32_t key_right;
35 uint32_t key_left_alt;
36 uint32_t key_right_alt;
37 } RotaryCoderState;
39 static void rotary_update(RotaryCoderState *s, int direction)
41 s->state += direction;
42 s->state %= 4;
44 qemu_set_irq(s->out[0], s->state == 1 || s->state == 2);
45 qemu_set_irq(s->out[1], s->state == 2 || s->state == 3);
48 static void rotary_keyboard_event(void *opaque, int keycode)
50 RotaryCoderState *s = opaque;
52 if (keycode == 0xe0 && !s->extension) {
53 s->extension = 0x80;
54 return;
57 if (!(keycode & 0x80)) {
58 keycode &= 0x7f;
59 keycode |= s->extension;
61 if (keycode == s->key_left || keycode == s->key_left_alt) {
62 rotary_update(s, 3);
63 } else if (keycode == s->key_right || keycode == s->key_right_alt) {
64 rotary_update(s, 1);
68 s->extension = 0;
71 static void rotary_save(QEMUFile *f, void *opaque)
73 RotaryCoderState *s = opaque;
75 qemu_put_byte(f, s->state);
76 qemu_put_byte(f, s->extension);
79 static int rotary_load(QEMUFile *f, void *opaque, int version_id)
81 RotaryCoderState *s = opaque;
83 if (version_id != 1)
84 return -EINVAL;
86 s->state = qemu_get_byte(f);
87 s->extension = qemu_get_byte(f);
89 return 0;
93 static void rotary_late_init(DeviceState *dev)
95 RotaryCoderState *s = FROM_SYSBUS(RotaryCoderState, sysbus_from_qdev(dev));
97 rotary_update(s);
101 static void rotary_init(SysBusDevice *dev)
103 RotaryCoderState *s = FROM_SYSBUS(RotaryCoderState, dev);
105 qdev_init_gpio_out(&dev->qdev, s->out, 2);
106 qemu_add_kbd_event_handler(rotary_keyboard_event, s);
107 register_savevm("gpio_rotary", -1, 1, rotary_save, rotary_load, s);
110 static SysBusDeviceInfo rotary_info = {
111 .init = rotary_init,
112 /* .qdev.late_init = rotary_late_init, */
113 .qdev.name = "gpio,rotary",
114 .qdev.size = sizeof(RotaryCoderState),
115 .qdev.props = (Property[]) {
117 .name = "key-left",
118 .info = &qdev_prop_uint32,
119 .offset = offsetof(RotaryCoderState, key_left),
120 .defval = (uint32_t[]) { 0xcb },
123 .name = "key-right",
124 .info = &qdev_prop_uint32,
125 .offset = offsetof(RotaryCoderState, key_right),
126 .defval = (uint32_t[]) { 0xcd },
129 .name = "key-left-alt",
130 .info = &qdev_prop_uint32,
131 .offset = offsetof(RotaryCoderState, key_left_alt),
132 .defval = (uint32_t[]) { 0x4b },
135 .name = "key-right-alt",
136 .info = &qdev_prop_uint32,
137 .offset = offsetof(RotaryCoderState, key_right_alt),
138 .defval = (uint32_t[]) { 0x4d },
140 {/* end of list */}
144 static void rotary_register(void)
146 sysbus_register_withprop(&rotary_info);
149 device_init(rotary_register)