Preparation for improved u2f-passthru hidraw handle lifetimes: These callbacks can be implemented by the backing implementation, i.e. u2f-passthru or u2f-emulated.
The start callback is invoked when the device receives an INTR IN, and the stop callback is invoked when the endpoint has been unlinked/stopped. For a Linux guest, the start callback corresponds to the `hid_hw_open` and `hid_hw_close` routines, invoked whenever the first user opens, respectively the last user closes the emulated hidraw device. Signed-off-by: David Bouman <dbouma...@gmail.com> --- hw/usb/u2f.c | 23 +++++++++++++++++++++++ hw/usb/u2f.h | 5 +++++ 2 files changed, 28 insertions(+) diff --git a/hw/usb/u2f.c b/hw/usb/u2f.c index 1fb59cf404..cc1abd6c7d 100644 --- a/hw/usb/u2f.c +++ b/hw/usb/u2f.c @@ -253,6 +253,12 @@ static void u2f_key_handle_data(USBDevice *dev, USBPacket *p) case USB_TOKEN_IN: packet_in = u2f_pending_in_get(key); if (packet_in == NULL) { + U2FKeyClass *kc = U2F_KEY_GET_CLASS(key); + + /* An early INTR IN is sent to kick the device. */ + if (!key->started) { + key->started = (kc->start ? kc->start(key) : true); + } p->status = USB_RET_NAK; return; } @@ -317,6 +323,21 @@ const VMStateDescription vmstate_u2f_key = { } }; +static void u2f_ep_stopped(USBDevice *dev, USBEndpoint *ep) +{ + U2FKeyState *key = U2F_KEY(dev); + U2FKeyClass *kc = U2F_KEY_GET_CLASS(key); + + if (!key->started) { + return; + } + if (kc->stop) { + kc->stop(key); + } + key->started = false; +} + + static void u2f_key_class_init(ObjectClass *klass, void *data) { DeviceClass *dc = DEVICE_CLASS(klass); @@ -332,6 +353,8 @@ static void u2f_key_class_init(ObjectClass *klass, void *data) uc->unrealize = u2f_key_unrealize; dc->desc = "QEMU U2F key"; dc->vmsd = &vmstate_u2f_key; + + uc->ep_stopped = u2f_ep_stopped; } static const TypeInfo u2f_key_info = { diff --git a/hw/usb/u2f.h b/hw/usb/u2f.h index 8bff13141a..56d989c783 100644 --- a/hw/usb/u2f.h +++ b/hw/usb/u2f.h @@ -49,6 +49,9 @@ struct U2FKeyClass { const uint8_t packet[U2FHID_PACKET_SIZE]); void (*realize)(U2FKeyState *key, Error **errp); void (*unrealize)(U2FKeyState *key); + + bool (*start)(U2FKeyState *key); + void (*stop)(U2FKeyState *key); }; /* @@ -64,6 +67,8 @@ struct U2FKeyState { uint8_t pending_in_start; uint8_t pending_in_end; uint8_t pending_in_num; + + bool started; }; /* -- 2.34.1