aboutsummaryrefslogtreecommitdiff
path: root/hw/input
diff options
context:
space:
mode:
Diffstat (limited to 'hw/input')
-rw-r--r--hw/input/adb.c77
1 files changed, 77 insertions, 0 deletions
diff --git a/hw/input/adb.c b/hw/input/adb.c
index 21a9b3a..bb36ce6 100644
--- a/hw/input/adb.c
+++ b/hw/input/adb.c
@@ -27,6 +27,7 @@
#include "hw/qdev-properties.h"
#include "migration/vmstate.h"
#include "qemu/module.h"
+#include "qemu/timer.h"
#include "adb-internal.h"
/* error codes */
@@ -89,19 +90,92 @@ int adb_poll(ADBBusState *s, uint8_t *obuf, uint16_t poll_mask)
return olen;
}
+void adb_set_autopoll_enabled(ADBBusState *s, bool enabled)
+{
+ if (s->autopoll_enabled != enabled) {
+ s->autopoll_enabled = enabled;
+ if (s->autopoll_enabled) {
+ timer_mod(s->autopoll_timer,
+ qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL) +
+ s->autopoll_rate_ms);
+ } else {
+ timer_del(s->autopoll_timer);
+ }
+ }
+}
+
+void adb_set_autopoll_rate_ms(ADBBusState *s, int rate_ms)
+{
+ s->autopoll_rate_ms = rate_ms;
+
+ if (s->autopoll_enabled) {
+ timer_mod(s->autopoll_timer,
+ qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL) +
+ s->autopoll_rate_ms);
+ }
+}
+
+void adb_set_autopoll_mask(ADBBusState *s, uint16_t mask)
+{
+ if (s->autopoll_mask != mask) {
+ s->autopoll_mask = mask;
+ if (s->autopoll_enabled && s->autopoll_mask) {
+ timer_mod(s->autopoll_timer,
+ qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL) +
+ s->autopoll_rate_ms);
+ } else {
+ timer_del(s->autopoll_timer);
+ }
+ }
+}
+
+static void adb_autopoll(void *opaque)
+{
+ ADBBusState *s = opaque;
+
+ s->autopoll_cb(s->autopoll_cb_opaque);
+
+ timer_mod(s->autopoll_timer,
+ qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL) +
+ s->autopoll_rate_ms);
+}
+
+void adb_register_autopoll_callback(ADBBusState *s, void (*cb)(void *opaque),
+ void *opaque)
+{
+ s->autopoll_cb = cb;
+ s->autopoll_cb_opaque = opaque;
+}
+
static const VMStateDescription vmstate_adb_bus = {
.name = "adb_bus",
.version_id = 0,
.minimum_version_id = 0,
.fields = (VMStateField[]) {
+ VMSTATE_TIMER_PTR(autopoll_timer, ADBBusState),
+ VMSTATE_BOOL(autopoll_enabled, ADBBusState),
+ VMSTATE_UINT8(autopoll_rate_ms, ADBBusState),
+ VMSTATE_UINT16(autopoll_mask, ADBBusState),
VMSTATE_END_OF_LIST()
}
};
+static void adb_bus_reset(BusState *qbus)
+{
+ ADBBusState *adb_bus = ADB_BUS(qbus);
+
+ adb_bus->autopoll_enabled = false;
+ adb_bus->autopoll_mask = 0xffff;
+ adb_bus->autopoll_rate_ms = 20;
+}
+
static void adb_bus_realize(BusState *qbus, Error **errp)
{
ADBBusState *adb_bus = ADB_BUS(qbus);
+ adb_bus->autopoll_timer = timer_new_ms(QEMU_CLOCK_VIRTUAL, adb_autopoll,
+ adb_bus);
+
vmstate_register(NULL, -1, &vmstate_adb_bus, adb_bus);
}
@@ -109,6 +183,8 @@ static void adb_bus_unrealize(BusState *qbus)
{
ADBBusState *adb_bus = ADB_BUS(qbus);
+ timer_del(adb_bus->autopoll_timer);
+
vmstate_unregister(NULL, &vmstate_adb_bus, adb_bus);
}
@@ -118,6 +194,7 @@ static void adb_bus_class_init(ObjectClass *klass, void *data)
k->realize = adb_bus_realize;
k->unrealize = adb_bus_unrealize;
+ k->reset = adb_bus_reset;
}
static const TypeInfo adb_bus_type_info = {