> > Allows to reuse code for emulating a character device. > It will be used for Smardcard test. > > Signed-off-by: Frediano Ziglio <fziglio@xxxxxxxxxx> > Acked-by: Victor Toso <victortoso@xxxxxxxxxx> > --- > server/tests/Makefile.am | 2 + > server/tests/meson.build | 2 + > server/tests/test-stream-device.c | 224 +++++++++--------------------- > server/tests/vmc-emu.c | 121 ++++++++++++++++ > server/tests/vmc-emu.h | 48 +++++++ > 5 files changed, 236 insertions(+), 161 deletions(-) > create mode 100644 server/tests/vmc-emu.c > create mode 100644 server/tests/vmc-emu.h > ... > diff --git a/server/tests/vmc-emu.c b/server/tests/vmc-emu.c > new file mode 100644 > index 000000000..ddac5269c > --- /dev/null > +++ b/server/tests/vmc-emu.c > @@ -0,0 +1,121 @@ > +/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */ > +/* > + Copyright (C) 2019 Red Hat, Inc. > + > + This library is free software; you can redistribute it and/or > + modify it under the terms of the GNU Lesser General Public > + License as published by the Free Software Foundation; either > + version 2.1 of the License, or (at your option) any later version. > + > + This library is distributed in the hope that it will be useful, > + but WITHOUT ANY WARRANTY; without even the implied warranty of > + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU > + Lesser General Public License for more details. > + > + You should have received a copy of the GNU Lesser General Public > + License along with this library; if not, see > <http://www.gnu.org/licenses/>. > +*/ > + > +#include <config.h> > +#include <glib.h> > + > +#include "vmc-emu.h" > + > +// handle writes to the device > +static int vmc_write(SpiceCharDeviceInstance *sin, > + const uint8_t *buf, int len) > +{ > + VmcEmu *const vmc = SPICE_CONTAINEROF(sin, VmcEmu, instance); > + > + // just copy into the buffer > + unsigned copy = MIN(sizeof(vmc->write_buf) - vmc->write_pos, len); > + memcpy(vmc->write_buf+vmc->write_pos, buf, copy); > + vmc->write_pos += copy; > + return len; > +} > + > +static int vmc_read(SpiceCharDeviceInstance *sin, > + uint8_t *buf, int len) > +{ > + VmcEmu *const vmc = SPICE_CONTAINEROF(sin, VmcEmu, instance); > + int ret; > + > + if (vmc->pos >= *vmc->message_sizes_curr && vmc->message_sizes_curr < > vmc->message_sizes_end) { > + ++vmc->message_sizes_curr; > + } > + if (vmc->message_sizes_curr >= vmc->message_sizes_end || vmc->pos >= > *vmc->message_sizes_curr) { > + return 0; > + } > + ret = MIN(*vmc->message_sizes_curr - vmc->pos, len); > + memcpy(buf, &vmc->message[vmc->pos], ret); > + vmc->pos += ret; > + // kick off next message read > + // currently Qemu kicks the device so we need to do it manually > + // here. If not all data are read, the device goes into blocking > + // state and we get the wake only when we read from the device > + // again > + if (vmc->pos >= *vmc->message_sizes_curr) { > + spice_server_char_device_wakeup(&vmc->instance); > + } > + return ret; > +} > + > +static void vmc_state(SpiceCharDeviceInstance *sin, > + int connected) > +{ > + VmcEmu *const vmc = SPICE_CONTAINEROF(sin, VmcEmu, instance); > + vmc->device_enabled = !!connected; > +} > + > +static const SpiceCharDeviceInterface vmc_interface = { > + .base = { > + .type = SPICE_INTERFACE_CHAR_DEVICE, > + .description = "test spice virtual channel char device", > + .major_version = SPICE_INTERFACE_CHAR_DEVICE_MAJOR, > + .minor_version = SPICE_INTERFACE_CHAR_DEVICE_MINOR, > + }, > + .state = vmc_state, > + .write = vmc_write, > + .read = vmc_read, > +}; > + > +VmcEmu *vmc_emu_new(const char *subtype, const char *portname) > +{ > + VmcEmu *vmc = g_new0(VmcEmu, 1); > + vmc->interface = vmc_interface; > + vmc->instance.base.sif = &vmc->interface.base; > + vmc->instance.subtype = g_strdup(subtype); > + if (portname) { > + vmc->instance.portname = g_strdup(portname); > + } > + vmc_emu_reset(vmc); > + return vmc; > +} > + > +void vmc_emu_destroy(VmcEmu *vmc) > +{ > + g_free((char *) vmc->instance.portname); > + g_free((char *) vmc->instance.subtype); > + g_free(vmc); > +} > + > +void vmc_emu_reset(VmcEmu *vmc) > +{ > + vmc->pos = 0; > + vmc->write_pos = 0; > + vmc->message_sizes_curr = vmc->message_sizes; > + vmc->message_sizes_end = vmc->message_sizes; > +} > + > +void vmc_emu_add_read_till(VmcEmu *vmc, uint8_t *end) > +{ > + g_assert(vmc->message_sizes_end - vmc->message_sizes < > G_N_ELEMENTS(vmc->message_sizes)); > + g_assert(end >= vmc->message); > + g_assert(end - vmc->message <= G_N_ELEMENTS(vmc->message)); > + unsigned prev_size = > + vmc->message_sizes_end > vmc->message_sizes ? > vmc->message_sizes_end[-1] : 0; > + unsigned size = end - vmc->message; > + g_assert(size >= prev_size); > + *vmc->message_sizes_end = size; > + ++vmc->message_sizes_end; > +} > diff --git a/server/tests/vmc-emu.h b/server/tests/vmc-emu.h > new file mode 100644 > index 000000000..6fcea69d2 > --- /dev/null > +++ b/server/tests/vmc-emu.h > @@ -0,0 +1,48 @@ > +/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */ > +/* > + Copyright (C) 2019 Red Hat, Inc. > + > + This library is free software; you can redistribute it and/or > + modify it under the terms of the GNU Lesser General Public > + License as published by the Free Software Foundation; either > + version 2.1 of the License, or (at your option) any later version. > + > + This library is distributed in the hope that it will be useful, > + but WITHOUT ANY WARRANTY; without even the implied warranty of > + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU > + Lesser General Public License for more details. > + > + You should have received a copy of the GNU Lesser General Public > + License along with this library; if not, see > <http://www.gnu.org/licenses/>. > +*/ > +#pragma once > + > +#include "char-device.h" > + > +typedef struct VmcEmu VmcEmu; > + > +struct VmcEmu { > + SpiceCharDeviceInterface interface; Locally I renamed this field to vmc_interface to avoid collision on Windows (detected by Gitlab CI) > + SpiceCharDeviceInstance instance; > + > + // device buffer to read from > + uint8_t message[2048]; > + // position to read from > + unsigned pos; > + > + // array of limits when the read should return > + // the array is defined as [message_sizes_curr, message_sizes_end) > + // then the size is reach we move on next one till exausted > + unsigned message_sizes[16]; > + unsigned *message_sizes_end, *message_sizes_curr; > + > + bool device_enabled; > + > + unsigned write_pos; > + uint8_t write_buf[2048]; > +}; > + > +VmcEmu *vmc_emu_new(const char *subtype, const char *portname); > +void vmc_emu_destroy(VmcEmu *vmc); > +void vmc_emu_reset(VmcEmu *vmc); > +void vmc_emu_add_read_till(VmcEmu *vmc, uint8_t *end); Frediano _______________________________________________ Spice-devel mailing list Spice-devel@xxxxxxxxxxxxxxxxxxxxx https://lists.freedesktop.org/mailman/listinfo/spice-devel