aboutsummaryrefslogtreecommitdiff
path: root/hw
diff options
context:
space:
mode:
authorRichard Henderson <richard.henderson@linaro.org>2022-06-14 06:21:46 -0700
committerRichard Henderson <richard.henderson@linaro.org>2022-06-14 06:21:46 -0700
commit8e6c70b9d4a1b1f3011805947925cfdb31642f7f (patch)
tree9685e05d394391bd955e0883c2c3f72f5381b9c5 /hw
parentdebd0753663bc89c86f5462a53268f2e3f680f60 (diff)
parentb95b56311a0890da0c9f7fc624529c3d7f8dbce0 (diff)
downloadqemu-8e6c70b9d4a1b1f3011805947925cfdb31642f7f.zip
qemu-8e6c70b9d4a1b1f3011805947925cfdb31642f7f.tar.gz
qemu-8e6c70b9d4a1b1f3011805947925cfdb31642f7f.tar.bz2
Merge tag 'kraxel-20220614-pull-request' of git://git.kraxel.org/qemu into staging
usb: add CanoKey device, fixes for ehci + redir ui: fixes for gtk and cocoa, rework refresh rate virtio-gpu: scanout flush fix # -----BEGIN PGP SIGNATURE----- # # iQIzBAABCgAdFiEEoDKM/7k6F6eZAf59TLbY7tPocTgFAmKoe/8ACgkQTLbY7tPo # cTgZqw/9HD5dMjP74jwrf14dSCR6FD8PfSZU43YBZtMKMtYIzSgrG0NGmreDIhmr # ZM+G0By+J8vFaSqDukX31077DnptyrxsANOg3zc28SfOCrI7I/mNVymd9hl+Ydpd # A7h0DpHxs1mkpTVxGoXZoJRGXUE41rctbFVjG3CGynSG9K2vFQRsJz0jG723dg5Y # uv+Di1WkhqNkyKNsTEGbz9LNqtdtGzvQm3COBpKoTsl4X3EXIE68Qh7i3cMTSNIw # KKPARW3oiCOy3Fc4kQW9nSxkkHMS6NPL1uyQ52j7pXYxRdxRaREFQ9Gxst3ie9bS # mbqSuzS2+1v0w37bq9wE0PiCkmwWnu2KWiWWkAIYlmmZTgHvgxCvPcJaeItmap27 # dsAuPUGBbhhrmUwfMgJXp/wRvoZQc2l9w9+eUklsbI+VTbr6i+r/OoLRmnDJr+K/ # yNscMU1LzoigK0NDdP+PnFl3k8pux0Awtotgfyd+UGTSW8a5L6UFAWIxcUcd0Jjv # 24jAEEc1S1ciDxJDWYn4+17KJARG7no2PRXsGXCUNaWduGEk8wPK+i6Xk82U36o7 # 7j0N16RFNv1YSUaUJHgtmAMRJIQMCiB42VaYxlDfzKupvq2RgRWaWBD/HozgLhXn # DjEX+JRAnaOYnn1NURzTNDwnhQethJRXI1ntI1U8IFLYT4baSCY= # =L5PO # -----END PGP SIGNATURE----- # gpg: Signature made Tue 14 Jun 2022 05:15:59 AM PDT # gpg: using RSA key A0328CFFB93A17A79901FE7D4CB6D8EED3E87138 # gpg: Good signature from "Gerd Hoffmann (work) <kraxel@redhat.com>" [undefined] # gpg: aka "Gerd Hoffmann <gerd@kraxel.org>" [undefined] # gpg: aka "Gerd Hoffmann (private) <kraxel@gmail.com>" [undefined] # gpg: WARNING: This key is not certified with a trusted signature! # gpg: There is no indication that the signature belongs to the owner. # Primary key fingerprint: A032 8CFF B93A 17A7 9901 FE7D 4CB6 D8EE D3E8 7138 * tag 'kraxel-20220614-pull-request' of git://git.kraxel.org/qemu: virtio-gpu: Respect UI refresh rate for EDID ui: Deliver refresh rate via QemuUIInfo ui/console: Do not return a value with ui_info virtio-gpu: update done only on the scanout associated with rect usbredir: avoid queuing hello packet on snapshot restore hw/usb/hcd-ehci: fix writeback order MAINTAINERS: add myself as CanoKey maintainer docs/system/devices/usb: Add CanoKey to USB devices examples docs: Add CanoKey documentation meson: Add CanoKey hw/usb/canokey: Add trace events hw/usb: Add CanoKey Implementation ui/cocoa: Fix poweroff request code ui/gtk-gl-area: create the requested GL context version ui/gtk-gl-area: implement GL context destruction Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
Diffstat (limited to 'hw')
-rw-r--r--hw/display/virtio-gpu-base.c7
-rw-r--r--hw/display/virtio-gpu.c4
-rw-r--r--hw/display/virtio-vga.c5
-rw-r--r--hw/display/xenfb.c14
-rw-r--r--hw/usb/Kconfig5
-rw-r--r--hw/usb/canokey.c313
-rw-r--r--hw/usb/canokey.h69
-rw-r--r--hw/usb/hcd-ehci.c5
-rw-r--r--hw/usb/meson.build5
-rw-r--r--hw/usb/redirect.c3
-rw-r--r--hw/usb/trace-events16
-rw-r--r--hw/vfio/display.c8
12 files changed, 438 insertions, 16 deletions
diff --git a/hw/display/virtio-gpu-base.c b/hw/display/virtio-gpu-base.c
index 790cec3..a29f191 100644
--- a/hw/display/virtio-gpu-base.c
+++ b/hw/display/virtio-gpu-base.c
@@ -69,16 +69,17 @@ static void virtio_gpu_notify_event(VirtIOGPUBase *g, uint32_t event_type)
virtio_notify_config(&g->parent_obj);
}
-static int virtio_gpu_ui_info(void *opaque, uint32_t idx, QemuUIInfo *info)
+static void virtio_gpu_ui_info(void *opaque, uint32_t idx, QemuUIInfo *info)
{
VirtIOGPUBase *g = opaque;
if (idx >= g->conf.max_outputs) {
- return -1;
+ return;
}
g->req_state[idx].x = info->xoff;
g->req_state[idx].y = info->yoff;
+ g->req_state[idx].refresh_rate = info->refresh_rate;
g->req_state[idx].width = info->width;
g->req_state[idx].height = info->height;
g->req_state[idx].width_mm = info->width_mm;
@@ -92,7 +93,7 @@ static int virtio_gpu_ui_info(void *opaque, uint32_t idx, QemuUIInfo *info)
/* send event to guest */
virtio_gpu_notify_event(g, VIRTIO_GPU_EVENT_DISPLAY);
- return 0;
+ return;
}
static void
diff --git a/hw/display/virtio-gpu.c b/hw/display/virtio-gpu.c
index cd4a560..20cc703 100644
--- a/hw/display/virtio-gpu.c
+++ b/hw/display/virtio-gpu.c
@@ -217,6 +217,7 @@ virtio_gpu_generate_edid(VirtIOGPU *g, int scanout,
.height_mm = b->req_state[scanout].height_mm,
.prefx = b->req_state[scanout].width,
.prefy = b->req_state[scanout].height,
+ .refresh_rate = b->req_state[scanout].refresh_rate,
};
edid->size = cpu_to_le32(sizeof(edid->edid));
@@ -514,6 +515,9 @@ static void virtio_gpu_resource_flush(VirtIOGPU *g,
for (i = 0; i < g->parent_obj.conf.max_outputs; i++) {
scanout = &g->parent_obj.scanout[i];
if (scanout->resource_id == res->resource_id &&
+ rf.r.x >= scanout->x && rf.r.y >= scanout->y &&
+ rf.r.x + rf.r.width <= scanout->x + scanout->width &&
+ rf.r.y + rf.r.height <= scanout->y + scanout->height &&
console_has_gl(scanout->con)) {
dpy_gl_update(scanout->con, 0, 0, scanout->width,
scanout->height);
diff --git a/hw/display/virtio-vga.c b/hw/display/virtio-vga.c
index c206b5d..4dcb34c 100644
--- a/hw/display/virtio-vga.c
+++ b/hw/display/virtio-vga.c
@@ -47,15 +47,14 @@ static void virtio_vga_base_text_update(void *opaque, console_ch_t *chardata)
}
}
-static int virtio_vga_base_ui_info(void *opaque, uint32_t idx, QemuUIInfo *info)
+static void virtio_vga_base_ui_info(void *opaque, uint32_t idx, QemuUIInfo *info)
{
VirtIOVGABase *vvga = opaque;
VirtIOGPUBase *g = vvga->vgpu;
if (g->hw_ops->ui_info) {
- return g->hw_ops->ui_info(g, idx, info);
+ g->hw_ops->ui_info(g, idx, info);
}
- return -1;
}
static void virtio_vga_base_gl_block(void *opaque, bool block)
diff --git a/hw/display/xenfb.c b/hw/display/xenfb.c
index cea10fe..50857cd 100644
--- a/hw/display/xenfb.c
+++ b/hw/display/xenfb.c
@@ -777,16 +777,24 @@ static void xenfb_update(void *opaque)
xenfb->up_fullscreen = 0;
}
-static void xenfb_update_interval(void *opaque, uint64_t interval)
+static void xenfb_ui_info(void *opaque, uint32_t idx, QemuUIInfo *info)
{
struct XenFB *xenfb = opaque;
+ uint32_t refresh_rate;
if (xenfb->feature_update) {
#ifdef XENFB_TYPE_REFRESH_PERIOD
if (xenfb_queue_full(xenfb)) {
return;
}
- xenfb_send_refresh_period(xenfb, interval);
+
+ refresh_rate = info->refresh_rate;
+ if (!refresh_rate) {
+ refresh_rate = 75;
+ }
+
+ /* T = 1 / f = 1 [s*Hz] / f = 1000*1000 [ms*mHz] / f */
+ xenfb_send_refresh_period(xenfb, 1000 * 1000 / refresh_rate);
#endif
}
}
@@ -983,5 +991,5 @@ struct XenDevOps xen_framebuffer_ops = {
static const GraphicHwOps xenfb_ops = {
.invalidate = xenfb_invalidate,
.gfx_update = xenfb_update,
- .update_interval = xenfb_update_interval,
+ .ui_info = xenfb_ui_info,
};
diff --git a/hw/usb/Kconfig b/hw/usb/Kconfig
index 53f8283..ce4f433 100644
--- a/hw/usb/Kconfig
+++ b/hw/usb/Kconfig
@@ -119,6 +119,11 @@ config USB_U2F
default y
depends on USB
+config USB_CANOKEY
+ bool
+ default y
+ depends on USB
+
config IMX_USBPHY
bool
default y
diff --git a/hw/usb/canokey.c b/hw/usb/canokey.c
new file mode 100644
index 0000000..4a08b1c
--- /dev/null
+++ b/hw/usb/canokey.c
@@ -0,0 +1,313 @@
+/*
+ * CanoKey QEMU device implementation.
+ *
+ * Copyright (c) 2021-2022 Canokeys.org <contact@canokeys.org>
+ * Written by Hongren (Zenithal) Zheng <i@zenithal.me>
+ *
+ * This code is licensed under the Apache-2.0.
+ */
+
+#include "qemu/osdep.h"
+#include <canokey-qemu.h>
+
+#include "qemu/module.h"
+#include "qapi/error.h"
+#include "hw/usb.h"
+#include "hw/qdev-properties.h"
+#include "trace.h"
+#include "desc.h"
+#include "canokey.h"
+
+#define CANOKEY_EP_IN(ep) ((ep) & 0x7F)
+
+#define CANOKEY_VENDOR_NUM 0x20a0
+#define CANOKEY_PRODUCT_NUM 0x42d2
+
+/*
+ * placeholder, canokey-qemu implements its own usb desc
+ * Namely we do not use usb_desc_handle_contorl
+ */
+enum {
+ STR_MANUFACTURER = 1,
+ STR_PRODUCT,
+ STR_SERIALNUMBER
+};
+
+static const USBDescStrings desc_strings = {
+ [STR_MANUFACTURER] = "canokeys.org",
+ [STR_PRODUCT] = "CanoKey QEMU",
+ [STR_SERIALNUMBER] = "0"
+};
+
+static const USBDescDevice desc_device_canokey = {
+ .bcdUSB = 0x0,
+ .bMaxPacketSize0 = 16,
+ .bNumConfigurations = 0,
+ .confs = NULL,
+};
+
+static const USBDesc desc_canokey = {
+ .id = {
+ .idVendor = CANOKEY_VENDOR_NUM,
+ .idProduct = CANOKEY_PRODUCT_NUM,
+ .bcdDevice = 0x0100,
+ .iManufacturer = STR_MANUFACTURER,
+ .iProduct = STR_PRODUCT,
+ .iSerialNumber = STR_SERIALNUMBER,
+ },
+ .full = &desc_device_canokey,
+ .high = &desc_device_canokey,
+ .str = desc_strings,
+};
+
+
+/*
+ * libcanokey-qemu.so side functions
+ * All functions are called from canokey_emu_device_loop
+ */
+int canokey_emu_stall_ep(void *base, uint8_t ep)
+{
+ trace_canokey_emu_stall_ep(ep);
+ CanoKeyState *key = base;
+ uint8_t ep_in = CANOKEY_EP_IN(ep); /* INTR IN has ep 129 */
+ key->ep_in_size[ep_in] = 0;
+ key->ep_in_state[ep_in] = CANOKEY_EP_IN_STALL;
+ return 0;
+}
+
+int canokey_emu_set_address(void *base, uint8_t addr)
+{
+ trace_canokey_emu_set_address(addr);
+ CanoKeyState *key = base;
+ key->dev.addr = addr;
+ return 0;
+}
+
+int canokey_emu_prepare_receive(
+ void *base, uint8_t ep, uint8_t *pbuf, uint16_t size)
+{
+ trace_canokey_emu_prepare_receive(ep, size);
+ CanoKeyState *key = base;
+ key->ep_out[ep] = pbuf;
+ key->ep_out_size[ep] = size;
+ return 0;
+}
+
+int canokey_emu_transmit(
+ void *base, uint8_t ep, const uint8_t *pbuf, uint16_t size)
+{
+ trace_canokey_emu_transmit(ep, size);
+ CanoKeyState *key = base;
+ uint8_t ep_in = CANOKEY_EP_IN(ep); /* INTR IN has ep 129 */
+ memcpy(key->ep_in[ep_in] + key->ep_in_size[ep_in],
+ pbuf, size);
+ key->ep_in_size[ep_in] += size;
+ key->ep_in_state[ep_in] = CANOKEY_EP_IN_READY;
+ /*
+ * ready for more data in device loop
+ *
+ * Note: this is a quirk for CanoKey CTAPHID
+ * because it calls multiple emu_transmit in one device_loop
+ * but w/o data_in it would stuck in device_loop
+ * This has no side effect for CCID as it is strictly
+ * OUT then IN transfer
+ * However it has side effect for Control transfer
+ */
+ if (ep_in != 0) {
+ canokey_emu_data_in(ep_in);
+ }
+ return 0;
+}
+
+uint32_t canokey_emu_get_rx_data_size(void *base, uint8_t ep)
+{
+ CanoKeyState *key = base;
+ return key->ep_out_size[ep];
+}
+
+/*
+ * QEMU side functions
+ */
+static void canokey_handle_reset(USBDevice *dev)
+{
+ trace_canokey_handle_reset();
+ CanoKeyState *key = CANOKEY(dev);
+ for (int i = 0; i != CANOKEY_EP_NUM; ++i) {
+ key->ep_in_state[i] = CANOKEY_EP_IN_WAIT;
+ key->ep_in_pos[i] = 0;
+ key->ep_in_size[i] = 0;
+ }
+ canokey_emu_reset();
+}
+
+static void canokey_handle_control(USBDevice *dev, USBPacket *p,
+ int request, int value, int index, int length, uint8_t *data)
+{
+ trace_canokey_handle_control_setup(request, value, index, length);
+ CanoKeyState *key = CANOKEY(dev);
+
+ canokey_emu_setup(request, value, index, length);
+
+ uint32_t dir_in = request & DeviceRequest;
+ if (!dir_in) {
+ /* OUT */
+ trace_canokey_handle_control_out();
+ if (key->ep_out[0] != NULL) {
+ memcpy(key->ep_out[0], data, length);
+ }
+ canokey_emu_data_out(p->ep->nr, data);
+ }
+
+ canokey_emu_device_loop();
+
+ /* IN */
+ switch (key->ep_in_state[0]) {
+ case CANOKEY_EP_IN_WAIT:
+ p->status = USB_RET_NAK;
+ break;
+ case CANOKEY_EP_IN_STALL:
+ p->status = USB_RET_STALL;
+ break;
+ case CANOKEY_EP_IN_READY:
+ memcpy(data, key->ep_in[0], key->ep_in_size[0]);
+ p->actual_length = key->ep_in_size[0];
+ trace_canokey_handle_control_in(p->actual_length);
+ /* reset state */
+ key->ep_in_state[0] = CANOKEY_EP_IN_WAIT;
+ key->ep_in_size[0] = 0;
+ key->ep_in_pos[0] = 0;
+ break;
+ }
+}
+
+static void canokey_handle_data(USBDevice *dev, USBPacket *p)
+{
+ CanoKeyState *key = CANOKEY(dev);
+
+ uint8_t ep_in = CANOKEY_EP_IN(p->ep->nr);
+ uint8_t ep_out = p->ep->nr;
+ uint32_t in_len;
+ uint32_t out_pos;
+ uint32_t out_len;
+ switch (p->pid) {
+ case USB_TOKEN_OUT:
+ trace_canokey_handle_data_out(ep_out, p->iov.size);
+ usb_packet_copy(p, key->ep_out_buffer[ep_out], p->iov.size);
+ out_pos = 0;
+ while (out_pos != p->iov.size) {
+ /*
+ * key->ep_out[ep_out] set by prepare_receive
+ * to be a buffer inside libcanokey-qemu.so
+ * key->ep_out_size[ep_out] set by prepare_receive
+ * to be the buffer length
+ */
+ out_len = MIN(p->iov.size - out_pos, key->ep_out_size[ep_out]);
+ memcpy(key->ep_out[ep_out],
+ key->ep_out_buffer[ep_out] + out_pos, out_len);
+ out_pos += out_len;
+ /* update ep_out_size to actual len */
+ key->ep_out_size[ep_out] = out_len;
+ canokey_emu_data_out(ep_out, NULL);
+ }
+ break;
+ case USB_TOKEN_IN:
+ if (key->ep_in_pos[ep_in] == 0) { /* first time IN */
+ canokey_emu_data_in(ep_in);
+ canokey_emu_device_loop(); /* may call transmit multiple times */
+ }
+ switch (key->ep_in_state[ep_in]) {
+ case CANOKEY_EP_IN_WAIT:
+ /* NAK for early INTR IN */
+ p->status = USB_RET_NAK;
+ break;
+ case CANOKEY_EP_IN_STALL:
+ p->status = USB_RET_STALL;
+ break;
+ case CANOKEY_EP_IN_READY:
+ /* submit part of ep_in buffer to USBPacket */
+ in_len = MIN(key->ep_in_size[ep_in] - key->ep_in_pos[ep_in],
+ p->iov.size);
+ usb_packet_copy(p,
+ key->ep_in[ep_in] + key->ep_in_pos[ep_in], in_len);
+ key->ep_in_pos[ep_in] += in_len;
+ /* reset state if all data submitted */
+ if (key->ep_in_pos[ep_in] == key->ep_in_size[ep_in]) {
+ key->ep_in_state[ep_in] = CANOKEY_EP_IN_WAIT;
+ key->ep_in_size[ep_in] = 0;
+ key->ep_in_pos[ep_in] = 0;
+ }
+ trace_canokey_handle_data_in(ep_in, in_len);
+ break;
+ }
+ break;
+ default:
+ p->status = USB_RET_STALL;
+ break;
+ }
+}
+
+static void canokey_realize(USBDevice *base, Error **errp)
+{
+ trace_canokey_realize();
+ CanoKeyState *key = CANOKEY(base);
+
+ if (key->file == NULL) {
+ error_setg(errp, "You must provide file=/path/to/canokey-file");
+ return;
+ }
+
+ usb_desc_init(base);
+
+ for (int i = 0; i != CANOKEY_EP_NUM; ++i) {
+ key->ep_in_state[i] = CANOKEY_EP_IN_WAIT;
+ key->ep_in_size[i] = 0;
+ key->ep_in_pos[i] = 0;
+ }
+
+ if (canokey_emu_init(key, key->file)) {
+ error_setg(errp, "canokey can not create or read %s", key->file);
+ return;
+ }
+}
+
+static void canokey_unrealize(USBDevice *base)
+{
+ trace_canokey_unrealize();
+}
+
+static Property canokey_properties[] = {
+ DEFINE_PROP_STRING("file", CanoKeyState, file),
+ DEFINE_PROP_END_OF_LIST(),
+};
+
+static void canokey_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ USBDeviceClass *uc = USB_DEVICE_CLASS(klass);
+
+ uc->product_desc = "CanoKey QEMU";
+ uc->usb_desc = &desc_canokey;
+ uc->handle_reset = canokey_handle_reset;
+ uc->handle_control = canokey_handle_control;
+ uc->handle_data = canokey_handle_data;
+ uc->handle_attach = usb_desc_attach;
+ uc->realize = canokey_realize;
+ uc->unrealize = canokey_unrealize;
+ dc->desc = "CanoKey QEMU";
+ device_class_set_props(dc, canokey_properties);
+ set_bit(DEVICE_CATEGORY_MISC, dc->categories);
+}
+
+static const TypeInfo canokey_info = {
+ .name = TYPE_CANOKEY,
+ .parent = TYPE_USB_DEVICE,
+ .instance_size = sizeof(CanoKeyState),
+ .class_init = canokey_class_init
+};
+
+static void canokey_register_types(void)
+{
+ type_register_static(&canokey_info);
+}
+
+type_init(canokey_register_types)
diff --git a/hw/usb/canokey.h b/hw/usb/canokey.h
new file mode 100644
index 0000000..24cf304
--- /dev/null
+++ b/hw/usb/canokey.h
@@ -0,0 +1,69 @@
+/*
+ * CanoKey QEMU device header.
+ *
+ * Copyright (c) 2021-2022 Canokeys.org <contact@canokeys.org>
+ * Written by Hongren (Zenithal) Zheng <i@zenithal.me>
+ *
+ * This code is licensed under the Apache-2.0.
+ */
+
+#ifndef CANOKEY_H
+#define CANOKEY_H
+
+#include "hw/qdev-core.h"
+
+#define TYPE_CANOKEY "canokey"
+#define CANOKEY(obj) \
+ OBJECT_CHECK(CanoKeyState, (obj), TYPE_CANOKEY)
+
+/*
+ * State of Canokey (i.e. hw/canokey.c)
+ */
+
+/* CTRL INTR BULK */
+#define CANOKEY_EP_NUM 3
+/* BULK/INTR IN can be up to 1352 bytes, e.g. get key info */
+#define CANOKEY_EP_IN_BUFFER_SIZE 2048
+/* BULK OUT can be up to 270 bytes, e.g. PIV import cert */
+#define CANOKEY_EP_OUT_BUFFER_SIZE 512
+
+typedef enum {
+ CANOKEY_EP_IN_WAIT,
+ CANOKEY_EP_IN_READY,
+ CANOKEY_EP_IN_STALL
+} CanoKeyEPState;
+
+typedef struct CanoKeyState {
+ USBDevice dev;
+
+ /* IN packets from canokey device loop */
+ uint8_t ep_in[CANOKEY_EP_NUM][CANOKEY_EP_IN_BUFFER_SIZE];
+ /*
+ * See canokey_emu_transmit
+ *
+ * For large INTR IN, receive multiple data from canokey device loop
+ * in this case ep_in_size would increase with every call
+ */
+ uint32_t ep_in_size[CANOKEY_EP_NUM];
+ /*
+ * Used in canokey_handle_data
+ * for IN larger than p->iov.size, we would do multiple handle_data()
+ *
+ * The difference between ep_in_pos and ep_in_size:
+ * We first increase ep_in_size to fill ep_in buffer in device_loop,
+ * then use ep_in_pos to submit data from ep_in buffer in handle_data
+ */
+ uint32_t ep_in_pos[CANOKEY_EP_NUM];
+ CanoKeyEPState ep_in_state[CANOKEY_EP_NUM];
+
+ /* OUT pointer to canokey recv buffer */
+ uint8_t *ep_out[CANOKEY_EP_NUM];
+ uint32_t ep_out_size[CANOKEY_EP_NUM];
+ /* For large BULK OUT, multiple write to ep_out is needed */
+ uint8_t ep_out_buffer[CANOKEY_EP_NUM][CANOKEY_EP_OUT_BUFFER_SIZE];
+
+ /* Properties */
+ char *file; /* canokey-file */
+} CanoKeyState;
+
+#endif /* CANOKEY_H */
diff --git a/hw/usb/hcd-ehci.c b/hw/usb/hcd-ehci.c
index 33a8a37..d4da8dc 100644
--- a/hw/usb/hcd-ehci.c
+++ b/hw/usb/hcd-ehci.c
@@ -2011,7 +2011,10 @@ static int ehci_state_writeback(EHCIQueue *q)
ehci_trace_qtd(q, NLPTR_GET(p->qtdaddr), (EHCIqtd *) &q->qh.next_qtd);
qtd = (uint32_t *) &q->qh.next_qtd;
addr = NLPTR_GET(p->qtdaddr);
- put_dwords(q->ehci, addr + 2 * sizeof(uint32_t), qtd + 2, 2);
+ /* First write back the offset */
+ put_dwords(q->ehci, addr + 3 * sizeof(uint32_t), qtd + 3, 1);
+ /* Then write back the token, clearing the 'active' bit */
+ put_dwords(q->ehci, addr + 2 * sizeof(uint32_t), qtd + 2, 1);
ehci_free_packet(p);
/*
diff --git a/hw/usb/meson.build b/hw/usb/meson.build
index de853d7..793df42 100644
--- a/hw/usb/meson.build
+++ b/hw/usb/meson.build
@@ -63,6 +63,11 @@ if u2f.found()
softmmu_ss.add(when: 'CONFIG_USB_U2F', if_true: [u2f, files('u2f-emulated.c')])
endif
+# CanoKey
+if canokey.found()
+ softmmu_ss.add(when: 'CONFIG_USB_CANOKEY', if_true: [canokey, files('canokey.c')])
+endif
+
# usb redirect
if usbredir.found()
usbredir_ss = ss.source_set()
diff --git a/hw/usb/redirect.c b/hw/usb/redirect.c
index fd7df59..1bd30ef 100644
--- a/hw/usb/redirect.c
+++ b/hw/usb/redirect.c
@@ -1280,7 +1280,8 @@ static void usbredir_create_parser(USBRedirDevice *dev)
}
#endif
- if (runstate_check(RUN_STATE_INMIGRATE)) {
+ if (runstate_check(RUN_STATE_INMIGRATE) ||
+ runstate_check(RUN_STATE_PRELAUNCH)) {
flags |= usbredirparser_fl_no_hello;
}
usbredirparser_init(dev->parser, VERSION, caps, USB_REDIR_CAPS_SIZE,
diff --git a/hw/usb/trace-events b/hw/usb/trace-events
index 9773cb5..914ca71 100644
--- a/hw/usb/trace-events
+++ b/hw/usb/trace-events
@@ -345,3 +345,19 @@ usb_serial_set_baud(int bus, int addr, int baud) "dev %d:%u baud rate %d"
usb_serial_set_data(int bus, int addr, int parity, int data, int stop) "dev %d:%u parity %c, data bits %d, stop bits %d"
usb_serial_set_flow_control(int bus, int addr, int index) "dev %d:%u flow control %d"
usb_serial_set_xonxoff(int bus, int addr, uint8_t xon, uint8_t xoff) "dev %d:%u xon 0x%x xoff 0x%x"
+
+# canokey.c
+canokey_emu_stall_ep(uint8_t ep) "ep %d"
+canokey_emu_set_address(uint8_t addr) "addr %d"
+canokey_emu_prepare_receive(uint8_t ep, uint16_t size) "ep %d size %d"
+canokey_emu_transmit(uint8_t ep, uint16_t size) "ep %d size %d"
+canokey_thread_start(void)
+canokey_thread_stop(void)
+canokey_handle_reset(void)
+canokey_handle_control_setup(int request, int value, int index, int length) "request 0x%04X value 0x%04X index 0x%04X length 0x%04X"
+canokey_handle_control_out(void)
+canokey_handle_control_in(int actual_len) "len %d"
+canokey_handle_data_out(uint8_t ep_out, uint32_t out_len) "ep %d len %d"
+canokey_handle_data_in(uint8_t ep_in, uint32_t in_len) "ep %d len %d"
+canokey_realize(void)
+canokey_unrealize(void)
diff --git a/hw/vfio/display.c b/hw/vfio/display.c
index 89bc905..78f4d82 100644
--- a/hw/vfio/display.c
+++ b/hw/vfio/display.c
@@ -106,14 +106,14 @@ err:
return;
}
-static int vfio_display_edid_ui_info(void *opaque, uint32_t idx,
- QemuUIInfo *info)
+static void vfio_display_edid_ui_info(void *opaque, uint32_t idx,
+ QemuUIInfo *info)
{
VFIOPCIDevice *vdev = opaque;
VFIODisplay *dpy = vdev->dpy;
if (!dpy->edid_regs) {
- return 0;
+ return;
}
if (info->width && info->height) {
@@ -121,8 +121,6 @@ static int vfio_display_edid_ui_info(void *opaque, uint32_t idx,
} else {
vfio_display_edid_update(vdev, false, 0, 0);
}
-
- return 0;
}
static void vfio_display_edid_init(VFIOPCIDevice *vdev)