diff options
-rw-r--r-- | hw/input/adb.c | 77 | ||||
-rw-r--r-- | include/hw/input/adb.h | 13 |
2 files changed, 90 insertions, 0 deletions
diff --git a/hw/input/adb.c b/hw/input/adb.c index 21a9b3aa96..bb36ce6fad 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 = { diff --git a/include/hw/input/adb.h b/include/hw/input/adb.h index 4d2c565f54..15b1874a3d 100644 --- a/include/hw/input/adb.h +++ b/include/hw/input/adb.h @@ -75,12 +75,25 @@ struct ADBBusState { ADBDevice *devices[MAX_ADB_DEVICES]; int nb_devices; int poll_index; + + QEMUTimer *autopoll_timer; + bool autopoll_enabled; + uint8_t autopoll_rate_ms; + uint16_t autopoll_mask; + void (*autopoll_cb)(void *opaque); + void *autopoll_cb_opaque; }; int adb_request(ADBBusState *s, uint8_t *buf_out, const uint8_t *buf, int len); int adb_poll(ADBBusState *s, uint8_t *buf_out, uint16_t poll_mask); +void adb_set_autopoll_enabled(ADBBusState *s, bool enabled); +void adb_set_autopoll_rate_ms(ADBBusState *s, int rate_ms); +void adb_set_autopoll_mask(ADBBusState *s, uint16_t mask); +void adb_register_autopoll_callback(ADBBusState *s, void (*cb)(void *opaque), + void *opaque); + #define TYPE_ADB_KEYBOARD "adb-keyboard" #define TYPE_ADB_MOUSE "adb-mouse" |