This patch series adds an audio device implementing the recent virtio sound spec (1.2) and a corresponding PCI wrapper device.
v8 can be found online at: https://gitlab.com/epilys/qemu/-/tree/virtio-snd-v8 Ref 69eb5f4fbae731f5fc05dea8a5f4b656e0de127f Main differences with v7 patch series [^v7] <[email protected]>: - Addressed [^v7] review comments. Functions that were called from more than one place for code re-use are not created until they are actually needed. - Fixed cases where block->offset was not respected in Playback Previously: [^v7] https://lore.kernel.org/qemu-devel/[email protected]/ [^v6]: https://lore.kernel.org/qemu-devel/[email protected]/ [^v5]: https://lore.kernel.org/qemu-devel/[email protected]/ [^v4]: https://lore.kernel.org/qemu-devel/[email protected]/ [^v3]: https://lore.kernel.org/qemu-devel/[email protected]/ Emmanouil Pitsidianakis (12): Add virtio-sound device stub Add virtio-sound-pci device virtio-sound: handle control messages and streams virtio-sound: set PCM stream parameters virtio-sound: handle VIRTIO_SND_R_PCM_INFO request virtio-sound: handle VIRTIO_SND_R_PCM_{START,STOP} virtio-sound: handle VIRTIO_SND_R_PCM_SET_PARAMS virtio-sound: handle VIRTIO_SND_R_PCM_PREPARE virtio-sound: handle VIRTIO_SND_R_PCM_RELEASE virtio-sound: implement audio output (TX) virtio-sound: implement audio capture (RX) docs/system: add basic virtio-snd documentation MAINTAINERS | 6 + docs/system/device-emulation.rst | 1 + docs/system/devices/virtio-snd.rst | 49 ++ hw/virtio/Kconfig | 5 + hw/virtio/meson.build | 2 + hw/virtio/trace-events | 20 + hw/virtio/virtio-snd-pci.c | 97 +++ hw/virtio/virtio-snd.c | 1308 ++++++++++++++++++++++++++++ include/hw/virtio/virtio-snd.h | 155 ++++ softmmu/qdev-monitor.c | 1 + 10 files changed, 1644 insertions(+) create mode 100644 docs/system/devices/virtio-snd.rst create mode 100644 hw/virtio/virtio-snd-pci.c create mode 100644 hw/virtio/virtio-snd.c create mode 100644 include/hw/virtio/virtio-snd.h Range-diff against v7: 1: 1a8ffb08d6 ! 1: 238de1757e Add virtio-sound device stub @@ Commit message Add a new VIRTIO device for the virtio sound device id. Functionality will be added in the following commits. + Based-on: https://github.com/OpenSynergy/qemu/commit/5a2f350eec5d157b90d9c7b40a8e603f4da92471 + Reviewed-by: Alex Bennée <[email protected]> + Signed-off-by: Igor Skalkin <[email protected]> + Signed-off-by: Anton Yakovlev <[email protected]> Signed-off-by: Emmanouil Pitsidianakis <[email protected]> ## MAINTAINERS ## @@ hw/virtio/virtio-snd.c (new) +#include "qemu/osdep.h" +#include "qemu/iov.h" +#include "qemu/log.h" ++#include "qemu/error-report.h" +#include "include/qemu/lockable.h" +#include "sysemu/runstate.h" +#include "trace.h" @@ hw/virtio/virtio-snd.c (new) + return features; +} + -+static void virtio_snd_common_realize(DeviceState *dev, -+ VirtIOHandleOutput ctrl, -+ VirtIOHandleOutput evt, -+ VirtIOHandleOutput txq, -+ VirtIOHandleOutput rxq, -+ Error **errp) ++static void ++virtio_snd_vm_state_change(void *opaque, bool running, ++ RunState state) +{ -+ VirtIODevice *vdev = VIRTIO_DEVICE(dev); ++ if (running) { ++ trace_virtio_snd_vm_state_running(); ++ } else { ++ trace_virtio_snd_vm_state_stopped(); ++ } ++} ++ ++static void virtio_snd_realize(DeviceState *dev, Error **errp) ++{ ++ ERRP_GUARD(); + VirtIOSound *vsnd = VIRTIO_SND(dev); ++ VirtIODevice *vdev = VIRTIO_DEVICE(dev); ++ ++ vsnd->vmstate = ++ qemu_add_vm_change_state_handler(virtio_snd_vm_state_change, vsnd); ++ ++ trace_virtio_snd_realize(vsnd); + + virtio_init(vdev, VIRTIO_ID_SOUND, sizeof(virtio_snd_config)); + virtio_add_feature(&vsnd->features, VIRTIO_F_VERSION_1); @@ hw/virtio/virtio-snd.c (new) + + AUD_register_card("virtio-sound", &vsnd->card); + -+ vsnd->queues[VIRTIO_SND_VQ_CONTROL] = virtio_add_queue(vdev, 64, ctrl); -+ vsnd->queues[VIRTIO_SND_VQ_EVENT] = virtio_add_queue(vdev, 64, evt); -+ vsnd->queues[VIRTIO_SND_VQ_TX] = virtio_add_queue(vdev, 64, txq); -+ vsnd->queues[VIRTIO_SND_VQ_RX] = virtio_add_queue(vdev, 64, rxq); -+} -+ -+static void -+virtio_snd_vm_state_change(void *, bool running, RunState) -+{ -+ if (running) { -+ trace_virtio_snd_vm_state_running(); -+ } else { -+ trace_virtio_snd_vm_state_stopped(); -+ } -+} -+ -+static void virtio_snd_realize(DeviceState *dev, Error **errp) -+{ -+ ERRP_GUARD(); -+ VirtIOSound *vsnd = VIRTIO_SND(dev); -+ -+ vsnd->vmstate = -+ qemu_add_vm_change_state_handler(virtio_snd_vm_state_change, vsnd); -+ -+ trace_virtio_snd_realize(vsnd); -+ -+ virtio_snd_common_realize(dev, -+ virtio_snd_handle_queue, -+ virtio_snd_handle_queue, -+ virtio_snd_handle_queue, -+ virtio_snd_handle_queue, -+ errp); ++ vsnd->queues[VIRTIO_SND_VQ_CONTROL] = ++ virtio_add_queue(vdev, 64, virtio_snd_handle_queue); ++ vsnd->queues[VIRTIO_SND_VQ_EVENT] = ++ virtio_add_queue(vdev, 64, virtio_snd_handle_queue); ++ vsnd->queues[VIRTIO_SND_VQ_TX] = ++ virtio_add_queue(vdev, 64, virtio_snd_handle_queue); ++ vsnd->queues[VIRTIO_SND_VQ_RX] = ++ virtio_add_queue(vdev, 64, virtio_snd_handle_queue); +} + +static void virtio_snd_unrealize(DeviceState *dev) 2: a32cf5571b ! 2: 8de966a86b Add virtio-sound-pci device @@ Commit message -audio driver=coreaudio,model=virtio etc. + Based-on: https://github.com/OpenSynergy/qemu/commit/5a2f350eec5d157b90d9c7b40a8e603f4da92471 + Reviewed-by: Alex Bennée <[email protected]> + Signed-off-by: Igor Skalkin <[email protected]> + Signed-off-by: Anton Yakovlev <[email protected]> Signed-off-by: Emmanouil Pitsidianakis <[email protected]> ## hw/virtio/meson.build ## 3: 3f43057c32 ! 3: e3e57dd125 virtio-sound: handle control messages and streams @@ Commit message The handler is process_cmd() which replies with VIRTIO_SND_S_NOT_SUPP. + Based-on: https://github.com/OpenSynergy/qemu/commit/5a2f350eec5d157b90d9c7b40a8e603f4da92471 + Reviewed-by: Alex Bennée <[email protected]> + Signed-off-by: Igor Skalkin <[email protected]> + Signed-off-by: Anton Yakovlev <[email protected]> Signed-off-by: Emmanouil Pitsidianakis <[email protected]> ## hw/virtio/trace-events ## @@ hw/virtio/virtio-snd.c: virtio_snd_set_config(VirtIODevice *vdev, const uint8_t static uint64_t get_features(VirtIODevice *vdev, uint64_t features, Error **errp) -@@ hw/virtio/virtio-snd.c: static uint64_t get_features(VirtIODevice *vdev, uint64_t features, - return features; +@@ hw/virtio/virtio-snd.c: virtio_snd_vm_state_change(void *opaque, bool running, + } } +static void virtio_snd_set_pcm(VirtIOSound *snd) @@ hw/virtio/virtio-snd.c: static uint64_t get_features(VirtIODevice *vdev, uint64_ + snd->pcm = pcm; +} + - static void virtio_snd_common_realize(DeviceState *dev, - VirtIOHandleOutput ctrl, - VirtIOHandleOutput evt, -@@ hw/virtio/virtio-snd.c: static void virtio_snd_common_realize(DeviceState *dev, - VirtIODevice *vdev = VIRTIO_DEVICE(dev); - VirtIOSound *vsnd = VIRTIO_SND(dev); - -+ virtio_snd_set_pcm(vsnd); -+ - virtio_init(vdev, VIRTIO_ID_SOUND, sizeof(virtio_snd_config)); - virtio_add_feature(&vsnd->features, VIRTIO_F_VERSION_1); - -@@ hw/virtio/virtio-snd.c: static void virtio_snd_common_realize(DeviceState *dev, - vsnd->queues[VIRTIO_SND_VQ_EVENT] = virtio_add_queue(vdev, 64, evt); - vsnd->queues[VIRTIO_SND_VQ_TX] = virtio_add_queue(vdev, 64, txq); - vsnd->queues[VIRTIO_SND_VQ_RX] = virtio_add_queue(vdev, 64, rxq); -+ qemu_mutex_init(&vsnd->cmdq_mutex); -+ QTAILQ_INIT(&vsnd->cmdq); - } - - static void -@@ hw/virtio/virtio-snd.c: static void virtio_snd_realize(DeviceState *dev, Error **errp) + static void virtio_snd_realize(DeviceState *dev, Error **errp) + { ERRP_GUARD(); VirtIOSound *vsnd = VIRTIO_SND(dev); + VirtIODevice *vdev = VIRTIO_DEVICE(dev); + vsnd->pcm = NULL; vsnd->vmstate = @@ hw/virtio/virtio-snd.c: static void virtio_snd_realize(DeviceState *dev, Error * trace_virtio_snd_realize(vsnd); - virtio_snd_common_realize(dev, -- virtio_snd_handle_queue, -- virtio_snd_handle_queue, -- virtio_snd_handle_queue, -- virtio_snd_handle_queue, -+ virtio_snd_handle_ctrl, -+ virtio_snd_handle_event, -+ virtio_snd_handle_xfer, -+ virtio_snd_handle_xfer, - errp); - } ++ virtio_snd_set_pcm(vsnd); ++ + virtio_init(vdev, VIRTIO_ID_SOUND, sizeof(virtio_snd_config)); + virtio_add_feature(&vsnd->features, VIRTIO_F_VERSION_1); + +@@ hw/virtio/virtio-snd.c: static void virtio_snd_realize(DeviceState *dev, Error **errp) + AUD_register_card("virtio-sound", &vsnd->card); + vsnd->queues[VIRTIO_SND_VQ_CONTROL] = +- virtio_add_queue(vdev, 64, virtio_snd_handle_queue); ++ virtio_add_queue(vdev, 64, virtio_snd_handle_ctrl); + vsnd->queues[VIRTIO_SND_VQ_EVENT] = +- virtio_add_queue(vdev, 64, virtio_snd_handle_queue); ++ virtio_add_queue(vdev, 64, virtio_snd_handle_event); + vsnd->queues[VIRTIO_SND_VQ_TX] = +- virtio_add_queue(vdev, 64, virtio_snd_handle_queue); ++ virtio_add_queue(vdev, 64, virtio_snd_handle_xfer); + vsnd->queues[VIRTIO_SND_VQ_RX] = +- virtio_add_queue(vdev, 64, virtio_snd_handle_queue); ++ virtio_add_queue(vdev, 64, virtio_snd_handle_xfer); ++ qemu_mutex_init(&vsnd->cmdq_mutex); ++ QTAILQ_INIT(&vsnd->cmdq); ++} ++ +/* + * Close the stream and free its resources. + * @@ hw/virtio/virtio-snd.c: static void virtio_snd_realize(DeviceState *dev, Error * + */ +static void virtio_snd_pcm_close(VirtIOSoundPCMStream *stream) +{ -+} -+ + } + static void virtio_snd_unrealize(DeviceState *dev) { VirtIODevice *vdev = VIRTIO_DEVICE(dev); 4: 34afff149a ! 4: 6b3f8d8206 virtio-sound: set PCM stream parameters @@ Commit message PCM parameters describe the sound card parameters that the guest's kernel sees as an ALSA device. + Based-on: https://github.com/OpenSynergy/qemu/commit/5a2f350eec5d157b90d9c7b40a8e603f4da92471 + Signed-off-by: Igor Skalkin <[email protected]> + Signed-off-by: Anton Yakovlev <[email protected]> Signed-off-by: Emmanouil Pitsidianakis <[email protected]> ## hw/virtio/virtio-snd.c ## @@ hw/virtio/virtio-snd.c: virtio_snd_set_config(VirtIODevice *vdev, const uint8_t + * @params: The PCM params as defined in the virtio specification + */ +static -+uint32_t virtio_snd_pcm_set_params_impl(VirtIOSound *s, -+ virtio_snd_pcm_set_params *params) ++uint32_t virtio_snd_set_pcm_params(VirtIOSound *s, ++ virtio_snd_pcm_set_params *params) +{ + VirtIOSoundPCMParams *st_params; + uint32_t stream_id = params->hdr.stream_id; @@ hw/virtio/virtio-snd.c: virtio_snd_set_config(VirtIODevice *vdev, const uint8_t + * @s: VirtIOSound device + * @stream_id: stream id + */ -+static uint32_t virtio_snd_pcm_prepare_impl(VirtIOSound *s, uint32_t stream_id) ++static uint32_t virtio_snd_pcm_prepare(VirtIOSound *s, uint32_t stream_id) +{ + audsettings as; + VirtIOSoundPCMParams *params; @@ hw/virtio/virtio-snd.c: virtio_snd_set_config(VirtIODevice *vdev, const uint8_t /* * The actual processing done in virtio_snd_process_cmdq(). * -@@ hw/virtio/virtio-snd.c: static void virtio_snd_common_realize(DeviceState *dev, - { - VirtIODevice *vdev = VIRTIO_DEVICE(dev); +@@ hw/virtio/virtio-snd.c: static void virtio_snd_realize(DeviceState *dev, Error **errp) + ERRP_GUARD(); VirtIOSound *vsnd = VIRTIO_SND(dev); + VirtIODevice *vdev = VIRTIO_DEVICE(dev); + virtio_snd_pcm_set_params default_params = { 0 }; + uint32_t status; - virtio_snd_set_pcm(vsnd); - -@@ hw/virtio/virtio-snd.c: static void virtio_snd_common_realize(DeviceState *dev, + vsnd->pcm = NULL; + vsnd->vmstate = +@@ hw/virtio/virtio-snd.c: static void virtio_snd_realize(DeviceState *dev, Error **errp) AUD_register_card("virtio-sound", &vsnd->card); + /* set default params for all streams */ + default_params.features = 0; -+ default_params.buffer_bytes = 16384; -+ default_params.period_bytes = 4096; ++ default_params.buffer_bytes = 8192; ++ default_params.period_bytes = 2048; + default_params.channels = 2; + default_params.format = VIRTIO_SND_PCM_FMT_S16; + default_params.rate = VIRTIO_SND_PCM_RATE_48000; - vsnd->queues[VIRTIO_SND_VQ_CONTROL] = virtio_add_queue(vdev, 64, ctrl); - vsnd->queues[VIRTIO_SND_VQ_EVENT] = virtio_add_queue(vdev, 64, evt); - vsnd->queues[VIRTIO_SND_VQ_TX] = virtio_add_queue(vdev, 64, txq); - vsnd->queues[VIRTIO_SND_VQ_RX] = virtio_add_queue(vdev, 64, rxq); + vsnd->queues[VIRTIO_SND_VQ_CONTROL] = + virtio_add_queue(vdev, 64, virtio_snd_handle_ctrl); + vsnd->queues[VIRTIO_SND_VQ_EVENT] = +@@ hw/virtio/virtio-snd.c: static void virtio_snd_realize(DeviceState *dev, Error **errp) + virtio_add_queue(vdev, 64, virtio_snd_handle_xfer); qemu_mutex_init(&vsnd->cmdq_mutex); QTAILQ_INIT(&vsnd->cmdq); -+ +-} + +-/* +- * Close the stream and free its resources. +- * +- * @stream: VirtIOSoundPCMStream *stream +- */ +-static void virtio_snd_pcm_close(VirtIOSoundPCMStream *stream) +-{ + for (uint32_t i = 0; i < vsnd->snd_conf.streams; i++) { + default_params.hdr.stream_id = i; -+ status = virtio_snd_pcm_set_params_impl(vsnd, &default_params); ++ status = virtio_snd_set_pcm_params(vsnd, &default_params); + if (status != VIRTIO_SND_S_OK) { + error_setg(errp, + "Can't initalize stream params, device responded with %s.", + print_code(status)); + return; + } -+ status = virtio_snd_pcm_prepare_impl(vsnd, i); ++ status = virtio_snd_pcm_prepare(vsnd, i); + if (status != VIRTIO_SND_S_OK) { + error_setg(errp, + "Can't prepare streams, device responded with %s.", @@ hw/virtio/virtio-snd.c: static void virtio_snd_common_realize(DeviceState *dev, + } } - static void -@@ hw/virtio/virtio-snd.c: static void virtio_snd_realize(DeviceState *dev, Error **errp) - errp); - } - --/* -- * Close the stream and free its resources. -- * -- * @stream: VirtIOSoundPCMStream *stream -- */ --static void virtio_snd_pcm_close(VirtIOSoundPCMStream *stream) --{ --} -- static void virtio_snd_unrealize(DeviceState *dev) - { - VirtIODevice *vdev = VIRTIO_DEVICE(dev); @@ hw/virtio/virtio-snd.c: static void virtio_snd_unrealize(DeviceState *dev) vsnd->pcm = NULL; } 5: 0f433debd3 ! 5: 974d88412d virtio-sound: handle VIRTIO_SND_R_PCM_INFO request @@ Commit message Respond to the VIRTIO_SND_R_PCM_INFO control request with the parameters of each requested PCM stream. + Based-on: https://github.com/OpenSynergy/qemu/commit/5a2f350eec5d157b90d9c7b40a8e603f4da92471 + Signed-off-by: Igor Skalkin <[email protected]> + Signed-off-by: Anton Yakovlev <[email protected]> Signed-off-by: Emmanouil Pitsidianakis <[email protected]> ## hw/virtio/trace-events ## 6: 70bb76519e ! 6: ff6f132004 virtio-sound: handle VIRTIO_SND_R_PCM_{START,STOP} @@ Commit message does nothing at the moment except for replying to it. Audio playback or capture will be started/stopped here in follow-up commits. + Based-on: https://github.com/OpenSynergy/qemu/commit/5a2f350eec5d157b90d9c7b40a8e603f4da92471 + Signed-off-by: Igor Skalkin <[email protected]> + Signed-off-by: Anton Yakovlev <[email protected]> Signed-off-by: Emmanouil Pitsidianakis <[email protected]> ## hw/virtio/trace-events ## @@ hw/virtio/trace-events: virtio_snd_realize(void *snd) "snd %p: realize" virtio_snd_handle_event(void) "event queue callback called" ## hw/virtio/virtio-snd.c ## -@@ hw/virtio/virtio-snd.c: static uint32_t virtio_snd_pcm_prepare_impl(VirtIOSound *s, uint32_t stream_id) +@@ hw/virtio/virtio-snd.c: static uint32_t virtio_snd_pcm_prepare(VirtIOSound *s, uint32_t stream_id) return VIRTIO_SND_S_OK; } 7: fb37cca76a ! 7: 993e6af394 virtio-sound: handle VIRTIO_SND_PCM_SET_PARAMS @@ Metadata Author: Emmanouil Pitsidianakis <[email protected]> ## Commit message ## - virtio-sound: handle VIRTIO_SND_PCM_SET_PARAMS + virtio-sound: handle VIRTIO_SND_R_PCM_SET_PARAMS Handle the set parameters control request. It reconfigures a stream based on a guest's preference if the values are valid and supported. + Based-on: https://github.com/OpenSynergy/qemu/commit/5a2f350eec5d157b90d9c7b40a8e603f4da92471 + Signed-off-by: Igor Skalkin <[email protected]> + Signed-off-by: Anton Yakovlev <[email protected]> Signed-off-by: Emmanouil Pitsidianakis <[email protected]> ## hw/virtio/trace-events ## @@ hw/virtio/trace-events: virtio_snd_vm_state_running(void) "vm state running" virtio_snd_handle_pcm_start_stop(const char *code, uint32_t stream) "%s called for stream %"PRIu32 ## hw/virtio/virtio-snd.c ## -@@ hw/virtio/virtio-snd.c: uint32_t virtio_snd_pcm_set_params_impl(VirtIOSound *s, +@@ hw/virtio/virtio-snd.c: uint32_t virtio_snd_set_pcm_params(VirtIOSound *s, return VIRTIO_SND_S_OK; } @@ hw/virtio/virtio-snd.c: uint32_t virtio_snd_pcm_set_params_impl(VirtIOSound *s, + } + + trace_virtio_snd_handle_pcm_set_params(req.hdr.stream_id); -+ cmd->resp.code = virtio_snd_pcm_set_params_impl(s, &req); ++ cmd->resp.code = virtio_snd_set_pcm_params(s, &req); +} + /* 8: 1e4bef953f ! 8: 36ce5f4d63 virtio-sound: handle VIRTIO_SND_R_PCM_PREPARE @@ Commit message Handles the PCM prepare control request. It initializes a PCM stream when the guests asks for it. + Based-on: https://github.com/OpenSynergy/qemu/commit/5a2f350eec5d157b90d9c7b40a8e603f4da92471 + Signed-off-by: Igor Skalkin <[email protected]> + Signed-off-by: Anton Yakovlev <[email protected]> Signed-off-by: Emmanouil Pitsidianakis <[email protected]> ## hw/virtio/virtio-snd.c ## -@@ hw/virtio/virtio-snd.c: static uint32_t virtio_snd_pcm_prepare_impl(VirtIOSound *s, uint32_t stream_id) +@@ hw/virtio/virtio-snd.c: static uint32_t virtio_snd_pcm_prepare(VirtIOSound *s, uint32_t stream_id) return VIRTIO_SND_S_OK; } @@ hw/virtio/virtio-snd.c: static uint32_t virtio_snd_pcm_prepare_impl(VirtIOSound + sizeof(stream_id)); + + cmd->resp.code = sz == sizeof(uint32_t) -+ ? virtio_snd_pcm_prepare_impl(s, stream_id) ++ ? virtio_snd_pcm_prepare(s, stream_id) + : VIRTIO_SND_S_BAD_MSG; +} + 9: b1bc6e7c21 ! 9: 30ad4bc665 virtio-sound: handle VIRTIO_SND_PCM_RELEASE @@ Metadata Author: Emmanouil Pitsidianakis <[email protected]> ## Commit message ## - virtio-sound: handle VIRTIO_SND_PCM_RELEASE + virtio-sound: handle VIRTIO_SND_R_PCM_RELEASE Handle the PCM release control request, which is necessary for flushing pending sound IO. No IO is handled yet so currently it only replies to the request. + Based-on: https://github.com/OpenSynergy/qemu/commit/5a2f350eec5d157b90d9c7b40a8e603f4da92471 + Signed-off-by: Igor Skalkin <[email protected]> + Signed-off-by: Anton Yakovlev <[email protected]> Signed-off-by: Emmanouil Pitsidianakis <[email protected]> ## hw/virtio/trace-events ## 10: fc27067092 ! 10: c94a9c1e65 virtio-sound: implement audio output (TX) @@ Commit message releasing all IO messages back to the guest. This is how according to the spec the guest knows the release was successful. + Based-on: https://github.com/OpenSynergy/qemu/commit/5a2f350eec5d157b90d9c7b40a8e603f4da92471 + Signed-off-by: Igor Skalkin <[email protected]> + Signed-off-by: Anton Yakovlev <[email protected]> Signed-off-by: Emmanouil Pitsidianakis <[email protected]> ## hw/virtio/trace-events ## @@ hw/virtio/virtio-snd.c: static void virtio_snd_get_qemu_audsettings(audsettings qemu_mutex_destroy(&stream->queue_mutex); g_free(stream); } -@@ hw/virtio/virtio-snd.c: static uint32_t virtio_snd_pcm_prepare_impl(VirtIOSound *s, uint32_t stream_id) +@@ hw/virtio/virtio-snd.c: static uint32_t virtio_snd_pcm_prepare(VirtIOSound *s, uint32_t stream_id) stream->positions[0] = VIRTIO_SND_CHMAP_FL; stream->positions[1] = VIRTIO_SND_CHMAP_FR; @@ hw/virtio/virtio-snd.c: static uint32_t virtio_snd_pcm_prepare_impl(VirtIOSound stream->as = as; stream->desired_as = stream->as; qemu_mutex_init(&stream->queue_mutex); +@@ hw/virtio/virtio-snd.c: static void virtio_snd_handle_pcm_start_stop(VirtIOSound *s, + bool start) + { + VirtIOSoundPCMStream *stream; ++ VirtIOSoundPCMBlock *block, *next; + virtio_snd_pcm_hdr req; + size_t sz = iov_to_buf(cmd->elem->out_sg, + cmd->elem->out_num, @@ hw/virtio/virtio-snd.c: static void virtio_snd_handle_pcm_start_stop(VirtIOSound *s, "VIRTIO_SND_R_PCM_STOP", req.stream_id); @@ hw/virtio/virtio-snd.c: static void virtio_snd_handle_pcm_start_stop(VirtIOSound + if (stream->direction == VIRTIO_SND_D_OUTPUT) { + AUD_set_active_out(stream->voice.out, start); + } ++ /* remove previous buffers. */ ++ WITH_QEMU_LOCK_GUARD(&stream->queue_mutex) { ++ QSIMPLEQ_FOREACH_SAFE(block, &stream->queue, entry, next) { ++ virtqueue_push(block->vq, ++ block->elem, ++ sizeof(block->elem)); ++ virtio_notify(VIRTIO_DEVICE(stream->s), block->vq); ++ QSIMPLEQ_REMOVE_HEAD(&stream->queue, entry); ++ g_free(block); ++ } ++ } + } else { error_report("Invalid stream id: %"PRIu32, req.stream_id); cmd->resp.code = VIRTIO_SND_S_BAD_MSG; @@ hw/virtio/virtio-snd.c: static void virtio_snd_handle_event(VirtIODevice *vdev, * Stub buffer virtqueue handler. * @@ hw/virtio/virtio-snd.c: static void virtio_snd_realize(DeviceState *dev, Error **errp) - virtio_snd_common_realize(dev, - virtio_snd_handle_ctrl, - virtio_snd_handle_event, -- virtio_snd_handle_xfer, -+ virtio_snd_handle_tx, - virtio_snd_handle_xfer, - errp); + vsnd->queues[VIRTIO_SND_VQ_EVENT] = + virtio_add_queue(vdev, 64, virtio_snd_handle_event); + vsnd->queues[VIRTIO_SND_VQ_TX] = +- virtio_add_queue(vdev, 64, virtio_snd_handle_xfer); ++ virtio_add_queue(vdev, 64, virtio_snd_handle_tx); + vsnd->queues[VIRTIO_SND_VQ_RX] = + virtio_add_queue(vdev, 64, virtio_snd_handle_xfer); + qemu_mutex_init(&vsnd->cmdq_mutex); +@@ hw/virtio/virtio-snd.c: static void virtio_snd_realize(DeviceState *dev, Error **errp) + } } +/* @@ hw/virtio/virtio-snd.c: static void virtio_snd_realize(DeviceState *dev, Error * + + WITH_QEMU_LOCK_GUARD(&stream->queue_mutex) { + QSIMPLEQ_FOREACH_SAFE(block, &stream->queue, entry, next) { -+ AUD_write(stream->voice.out, block->data, block->size); ++ AUD_write(stream->voice.out, block->data + block->offset, block->size); + virtqueue_push(block->vq, block->elem, sizeof(block->elem)); + virtio_notify(VIRTIO_DEVICE(stream->s), block->vq); + QSIMPLEQ_REMOVE(&stream->queue, block, VirtIOSoundPCMBlock, entry); 11: 770e8b2fe7 ! 11: 9a85da0dde virtio-sound: implement audio capture (RX) @@ hw/virtio/virtio-snd.c: static void virtio_snd_pcm_close(VirtIOSoundPCMStream *s } qemu_mutex_destroy(&stream->queue_mutex); g_free(stream); -@@ hw/virtio/virtio-snd.c: static uint32_t virtio_snd_pcm_prepare_impl(VirtIOSound *s, uint32_t stream_id) +@@ hw/virtio/virtio-snd.c: static uint32_t virtio_snd_pcm_prepare(VirtIOSound *s, uint32_t stream_id) virtio_snd_pcm_out_cb, &as); } else { @@ hw/virtio/virtio-snd.c: static void virtio_snd_handle_pcm_start_stop(VirtIOSound + } else { + AUD_set_active_in(stream->voice.in, start); } - } else { - error_report("Invalid stream id: %"PRIu32, req.stream_id); + /* remove previous buffers. */ + WITH_QEMU_LOCK_GUARD(&stream->queue_mutex) { @@ hw/virtio/virtio-snd.c: static void virtio_snd_handle_pcm_release(VirtIOSound *s, */ virtio_snd_process_cmdq(stream->s); @@ hw/virtio/virtio-snd.c: tx_err: static uint64_t get_features(VirtIODevice *vdev, uint64_t features, Error **errp) @@ hw/virtio/virtio-snd.c: static void virtio_snd_realize(DeviceState *dev, Error **errp) - virtio_snd_common_realize(dev, - virtio_snd_handle_ctrl, - virtio_snd_handle_event, -- virtio_snd_handle_tx, -- virtio_snd_handle_xfer, -+ virtio_snd_handle_tx_xfer, -+ virtio_snd_handle_rx_xfer, - errp); - } + vsnd->queues[VIRTIO_SND_VQ_EVENT] = + virtio_add_queue(vdev, 64, virtio_snd_handle_event); + vsnd->queues[VIRTIO_SND_VQ_TX] = +- virtio_add_queue(vdev, 64, virtio_snd_handle_tx); ++ virtio_add_queue(vdev, 64, virtio_snd_handle_tx_xfer); + vsnd->queues[VIRTIO_SND_VQ_RX] = +- virtio_add_queue(vdev, 64, virtio_snd_handle_xfer); ++ virtio_add_queue(vdev, 64, virtio_snd_handle_rx_xfer); + qemu_mutex_init(&vsnd->cmdq_mutex); + QTAILQ_INIT(&vsnd->cmdq); @@ hw/virtio/virtio-snd.c: static void virtio_snd_pcm_out_cb(void *data, int available) } @@ hw/virtio/virtio-snd.c: static void virtio_snd_pcm_out_cb(void *data, int availa WITH_QEMU_LOCK_GUARD(&stream->queue_mutex) { - QSIMPLEQ_FOREACH_SAFE(block, &stream->queue, entry, next) { -- AUD_write(stream->voice.out, block->data, block->size); +- AUD_write(stream->voice.out, block->data + block->offset, block->size); - virtqueue_push(block->vq, block->elem, sizeof(block->elem)); - virtio_notify(VIRTIO_DEVICE(stream->s), block->vq); - QSIMPLEQ_REMOVE(&stream->queue, block, VirtIOSoundPCMBlock, entry); @@ hw/virtio/virtio-snd.c: static void virtio_snd_pcm_out_cb(void *data, int availa +{ + virtio_snd_pcm_flush( + AUD_write(stream->voice.out, -+ block->data, -+ block->size); ++ block->data + block->offset, ++ block->size); + ); +} + 12: 6bed902247 = 12: 69eb5f4fba docs/system: add basic virtio-snd documentation base-commit: 50e7a40af372ee5931c99ef7390f5d3d6fbf6ec4 -- 2.39.2
