* [PATCH v4 00/12] Add VIRTIO sound card
@ 2023-07-20 12:57 Emmanouil Pitsidianakis
2023-07-20 12:57 ` [PATCH v4 01/12] Add virtio-sound device stub Emmanouil Pitsidianakis
` (11 more replies)
0 siblings, 12 replies; 22+ messages in thread
From: Emmanouil Pitsidianakis @ 2023-07-20 12:57 UTC (permalink / raw)
To: qemu-devel
Cc: Emmanouil Pitsidianakis, Igor Skalkin, Anton Yakovlev,
Paolo Bonzini, Gerd Hoffmann, Michael S. Tsirkin,
Marcel Apfelbaum, Daniel P. Berrangé, Eduardo Habkost,
Marc-André Lureau, Volker Rümelin,
Kővágó, Zoltán, Alex Bennee,
Philippe Mathieu-Daudé
This patch series adds an audio device implementing the recent virtio
sound spec (1.2) and a corresponding PCI wrapper device.
Main differences with v3 patch [^v3]
<cover.1689692765.git.manos.pitsidianakis@linaro.org>:
- Addressed review style comments.
- Split patches for easier review.
[^v3]:
https://lore.kernel.org/qemu-devel/cover.1689692765.git.manos.pitsidianakis@linaro.org/
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: prepare PCM streams
virtio-sound: handle VIRTIO_SND_R_PCM_INFO request
virtio-sound: handle VIRTIO_SND_R_PCM_{START,STOP}
virtio-sound: handle VIRTIO_SND_PCM_SET_PARAMS
virtio-sound: handle VIRTIO_SND_R_PCM_PREPARE
virtio-sound: handle VIRTIO_SND_PCM_RELEASE
virtio-sound: implement audio output (TX)
virtio-sound: implement audio capture (RX)
MAINTAINERS | 6 +
hw/virtio/Kconfig | 5 +
hw/virtio/meson.build | 2 +
hw/virtio/trace-events | 20 +
hw/virtio/virtio-snd-pci.c | 91 +++
hw/virtio/virtio-snd.c | 1298 ++++++++++++++++++++++++++++++++
include/hw/pci/pci.h | 1 +
include/hw/virtio/virtio-snd.h | 157 ++++
softmmu/qdev-monitor.c | 1 +
9 files changed, 1581 insertions(+)
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 v3:
1: 93c763e275 < -: ---------- Add virtio-sound device
-: ---------- > 1: ae372de565 Add virtio-sound device stub
2: 36373d92fa ! 2: 5cde5472ea Add virtio-sound-pci device
@@
## Metadata ##
-Author: Manos Pitsidianakis <manos.pitsidianakis@linaro.org>
+Author: Emmanouil Pitsidianakis <manos.pitsidianakis@linaro.org>
## Commit message ##
Add virtio-sound-pci device
This patch adds a PCI wrapper device for the virtio-sound device.
+ It is necessary to instantiate a virtio-snd device in a guest.
+ All sound logic will be added to the virtio-snd device in the following
+ commits.
- To test this, you'll need a >=5.13 kernel compiled with
- CONFIG_SND_VIRTIO=y, which at the time of writing most distros have off
- by default.
+ To add this device with a guest, you'll need a >=5.13 kernel compiled
+ with CONFIG_SND_VIRTIO=y, which at the time of writing most distros have
+ off by default.
Use with following flags in the invocation:
@@ Commit message
Pulseaudio:
-audio driver=pa,model=virtio-sound
+ or
+ -audio driver=pa,model=virtio-sound,server=/run/user/1000/pulse/native
sdl:
-audio driver=sdl,model=virtio-sound
coreaudio (macos/darwin):
-audio driver=coreaudio,model=virtio-sound
etc.
- You can use speaker-test from alsa-tools to play noise, sines, or
- WAV files.
-
Signed-off-by: Emmanouil Pitsidianakis <manos.pitsidianakis@linaro.org>
## hw/virtio/meson.build ##
@@ hw/virtio/virtio-snd-pci.c (new)
+{
+ VirtIOSoundPCI *dev = VIRTIO_SOUND_PCI(vpci_dev);
+ DeviceState *vdev = DEVICE(&dev->vdev);
-+ VirtIOSound *vsnd = VIRTIO_SND(&dev->vdev);
-+
-+ /*
-+ * According to spec, non-legacy virtio PCI devices are always little
-+ * endian
-+ */
-+ vsnd->virtio_access_is_big_endian = false;
-+
+
+ qdev_set_parent_bus(vdev, BUS(&vpci_dev->bus), errp);
-+
+ qdev_prop_set_string(vdev, "audiodev", audiodev_id);
-+
+ object_property_set_bool(OBJECT(vdev), "realized", true, errp);
+}
+
-: ---------- > 3: dc65cac2f4 virtio-sound: handle control messages and streams
-: ---------- > 4: bbd1799fc9 virtio-sound: set PCM stream parameters
-: ---------- > 5: 68a13c4385 virtio-sound: prepare PCM streams
-: ---------- > 6: f267d41957 virtio-sound: handle VIRTIO_SND_R_PCM_INFO request
-: ---------- > 7: 5939a6161e virtio-sound: handle VIRTIO_SND_R_PCM_{START,STOP}
-: ---------- > 8: 8f78d3a132 virtio-sound: handle VIRTIO_SND_PCM_SET_PARAMS
-: ---------- > 9: d2b3854084 virtio-sound: handle VIRTIO_SND_R_PCM_PREPARE
-: ---------- > 10: 4e14b2d129 virtio-sound: handle VIRTIO_SND_PCM_RELEASE
-: ---------- > 11: a6a0f07c7a virtio-sound: implement audio output (TX)
3: 8d432c85a2 ! 12: 1abb69dd05 Implement audio capture in virtio-snd device
@@
## Metadata ##
-Author: Manos Pitsidianakis <manos.pitsidianakis@linaro.org>
+Author: Emmanouil Pitsidianakis <manos.pitsidianakis@linaro.org>
## Commit message ##
- Implement audio capture in virtio-snd device
+ virtio-sound: implement audio capture (RX)
+
+ To perform audio capture we duplicate the TX logic of the previous
+ commit with the following difference: we receive data from the QEMU
+ audio backend and write it in the virt queue IO buffers the guest sends
+ to QEMU. When they are full (i.e. they have `period_bytes` amount of
+ data) or when recording stops in QEMU's audio backend, the buffer is
+ returned to the guest by notifying it.
Signed-off-by: Emmanouil Pitsidianakis <manos.pitsidianakis@linaro.org>
## hw/virtio/trace-events ##
-@@ hw/virtio/trace-events: virtio_snd_handle_pcm_set_params(int stream) "VIRTIO_SND_PCM_SET_PARAMS called f
- virtio_snd_handle_pcm_start_stop(const char *code, int stream) "%s called for stream %d"
- virtio_snd_handle_pcm_release(int stream) "VIRTIO_SND_PCM_RELEASE called for stream %d"
+@@ hw/virtio/trace-events: virtio_snd_handle_code(uint32_t val, const char *code) "ctrl code msg val = %"PR
virtio_snd_handle_chmap_info(void) "VIRTIO_SND_CHMAP_INFO called"
+ virtio_snd_handle_event(void) "event queue callback called"
+ virtio_snd_pcm_stream_flush(uint32_t stream) "flushing stream %"PRIu32
-virtio_snd_handle_xfer(void) "tx/rx queue callback called"
+virtio_snd_handle_tx_xfer(void) "tx queue callback called"
-+virtio_snd_handle_rx_xfer(void) "rx queue callback called"
- virtio_snd_handle_event(void) "event queue callback called"
- virtio_snd_realize(void *snd) "snd %p: realize"
- virtio_snd_unrealize(void *snd) "snd %p: unrealize"
++virtio_snd_handle_rx_xfer(void) "tx queue callback called"
## hw/virtio/virtio-snd.c ##
@@
- #define VIRTIO_SOUND_VM_VERSION 1
+ #define VIRTIO_SOUND_VM_VERSION 1
#define VIRTIO_SOUND_JACK_DEFAULT 0
-#define VIRTIO_SOUND_STREAM_DEFAULT 1
+#define VIRTIO_SOUND_STREAM_DEFAULT 2
#define VIRTIO_SOUND_CHMAP_DEFAULT 0
-
#define VIRTIO_SOUND_HDA_FN_NID 0
-@@ hw/virtio/virtio-snd.c: virtio_snd_set_config(VirtIODevice *vdev, const uint8_t *config)
- }
+ static void virtio_snd_pcm_out_cb(void *data, int available);
static void virtio_snd_process_cmdq(VirtIOSound *s);
-static void virtio_snd_pcm_flush(VirtIOSoundPCMStream *stream);
+-static uint32_t
+-virtio_snd_pcm_read_write(VirtIOSoundPCMStream *stream,
+- VirtQueue *vq,
+- VirtQueueElement *element,
+- bool read);
+static void virtio_snd_pcm_out_flush(VirtIOSoundPCMStream *stream);
+static void virtio_snd_pcm_in_flush(VirtIOSoundPCMStream *stream);
- static void virtio_snd_pcm_out_cb(void *data, int available);
--static uint32_t virtio_snd_pcm_read_write(VirtIOSoundPCMStream *stream,
+static void virtio_snd_pcm_in_cb(void *data, int available);
+static uint32_t virtio_snd_pcm_write(VirtIOSoundPCMStream *stream,
- VirtQueue *vq,
-- VirtQueueElement *element,
-- bool read);
-+ VirtQueueElement *element);
++ VirtQueue *vq,
++ VirtQueueElement *element);
+static uint32_t virtio_snd_pcm_read(VirtIOSoundPCMStream *stream,
-+ VirtQueue *vq,
-+ VirtQueueElement *element);
++ VirtQueue *vq,
++ VirtQueueElement *element);
- /*
- * Get a specific stream from the virtio sound card device.
+ static uint32_t supported_formats = BIT(VIRTIO_SND_PCM_FMT_S8)
+ | BIT(VIRTIO_SND_PCM_FMT_U8)
@@ hw/virtio/virtio-snd.c: static uint32_t virtio_snd_pcm_prepare_impl(VirtIOSound *s, uint32_t stream_id)
+ virtio_snd_pcm_out_cb,
&as);
-
} else {
- qemu_log_mask(LOG_UNIMP, "virtio_snd: input/capture is unimplemented.");
-- /*
-- * stream->voice.in = AUD_open_in(&s->card,
-- * stream->voice.in,
-- * "virtio_snd_card",
-- * stream,
-- * virtio_snd_input_cb,
-- * &as);
-- */
+ stream->voice.in = AUD_open_in(&s->card,
+ stream->voice.in,
+ "virtio_snd_card",
@@ hw/virtio/virtio-snd.c: static void virtio_snd_handle_pcm_start_stop(VirtIOSound
+ AUD_set_active_in(stream->voice.in, start);
}
} else {
- error_report("Invalid stream id: %d", req.stream_id);
+ error_report("Invalid stream id: %"PRIu32, req.stream_id);
@@ hw/virtio/virtio-snd.c: static uint32_t virtio_snd_pcm_release_impl(VirtIOSoundPCMStream *stream,
*/
virtio_snd_process_cmdq(stream->s);
@@ hw/virtio/virtio-snd.c: static void virtio_snd_handle_event(VirtIODevice *vdev,
* @vdev: VirtIOSound device
* @vq: tx virtqueue
*/
--static void virtio_snd_handle_xfer(VirtIODevice *vdev, VirtQueue *vq)
+-static void virtio_snd_handle_tx(VirtIODevice *vdev, VirtQueue *vq)
+static void virtio_snd_handle_tx_xfer(VirtIODevice *vdev, VirtQueue *vq)
{
VirtIOSound *s = VIRTIO_SND(vdev);
VirtIOSoundPCMStream *stream = NULL;
-@@ hw/virtio/virtio-snd.c: static void virtio_snd_handle_xfer(VirtIODevice *vdev, VirtQueue *vq)
+@@ hw/virtio/virtio-snd.c: static void virtio_snd_handle_tx(VirtIODevice *vdev, VirtQueue *vq)
virtio_snd_pcm_xfer hdr;
virtio_snd_pcm_status resp = { 0 };
@@ hw/virtio/virtio-snd.c: static void virtio_snd_handle_xfer(VirtIODevice *vdev, V
for (;;) {
elem = virtqueue_pop(vq, sizeof(VirtQueueElement));
-@@ hw/virtio/virtio-snd.c: static void virtio_snd_handle_xfer(VirtIODevice *vdev, VirtQueue *vq)
+@@ hw/virtio/virtio-snd.c: static void virtio_snd_handle_tx(VirtIODevice *vdev, VirtQueue *vq)
goto tx_err;
}
@@ hw/virtio/virtio-snd.c: static void virtio_snd_handle_xfer(VirtIODevice *vdev, V
resp.status = VIRTIO_SND_S_OK;
iov_from_buf(elem->in_sg,
@@ hw/virtio/virtio-snd.c: tx_err:
- virtio_notify(VIRTIO_DEVICE(s), vq);
}
-+/*
+ /*
+- * Stub buffer virtqueue handler.
+ * The rx virtqueue handler. Makes the buffers available to their respective
+ * streams for consumption.
-+ *
-+ * @vdev: VirtIOSound device
+ *
+ * @vdev: VirtIOSound device
+- * @vq: virtqueue
+ * @vq: tx virtqueue
-+ */
+ */
+-static void virtio_snd_handle_xfer(VirtIODevice *vdev, VirtQueue *vq) {}
+static void virtio_snd_handle_rx_xfer(VirtIODevice *vdev, VirtQueue *vq)
+{
+ VirtIOSound *s = VIRTIO_SND(vdev);
@@ hw/virtio/virtio-snd.c: tx_err:
+ */
+ virtio_notify(VIRTIO_DEVICE(s), vq);
+}
-+
-+
+
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_xfer,
+- virtio_snd_handle_tx,
- virtio_snd_handle_xfer,
+ virtio_snd_handle_tx_xfer,
+ virtio_snd_handle_rx_xfer,
@@ hw/virtio/virtio-snd.c: static void virtio_snd_pcm_out_cb(void *data, int availa
- VirtIOSoundPCMBlock *next;
+ uint32_t sz;
+ virtio_snd_pcm_status resp = { 0 };
-+ int size;
++ size_t size;
WITH_QEMU_LOCK_GUARD(&stream->queue_mutex) {
- QSIMPLEQ_FOREACH_SAFE(block, &stream->queue, entry, next) {
@@ hw/virtio/virtio-snd.c: static void virtio_snd_pcm_out_cb(void *data, int availa
+ MIN(stream->period_bytes - block->offset, available));
+ block->offset += size;
+ block->size += size;
-+ if (size == 0 || block->size == stream->period_bytes) {
++ if (size == 0 || block->size >= stream->period_bytes) {
+ resp.status = VIRTIO_SND_S_OK;
+ sz = iov_from_buf(block->elem->in_sg,
+ block->elem->in_num,
@@ hw/virtio/virtio-snd.c: static void virtio_snd_pcm_out_cb(void *data, int availa
+ block->elem->in_num,
+ sz,
+ &block->data,
-+ block->size);
++ MIN(stream->period_bytes, block->size));
+ }
+ virtqueue_push(block->vq,
+ block->elem,
base-commit: 2c27fdc7a626408ee2cf30d791aa0b63027c7404
--
2.39.2
^ permalink raw reply [flat|nested] 22+ messages in thread
* [PATCH v4 01/12] Add virtio-sound device stub
2023-07-20 12:57 [PATCH v4 00/12] Add VIRTIO sound card Emmanouil Pitsidianakis
@ 2023-07-20 12:57 ` Emmanouil Pitsidianakis
2023-07-25 14:22 ` Marc-André Lureau
2023-07-25 14:31 ` Marc-André Lureau
2023-07-20 12:57 ` [PATCH v4 02/12] Add virtio-sound-pci device Emmanouil Pitsidianakis
` (10 subsequent siblings)
11 siblings, 2 replies; 22+ messages in thread
From: Emmanouil Pitsidianakis @ 2023-07-20 12:57 UTC (permalink / raw)
To: qemu-devel
Cc: Emmanouil Pitsidianakis, Igor Skalkin, Anton Yakovlev,
Paolo Bonzini, Gerd Hoffmann, Michael S. Tsirkin,
Marcel Apfelbaum, Daniel P. Berrangé, Eduardo Habkost,
Marc-André Lureau, Volker Rümelin,
Kővágó, Zoltán, Alex Bennee,
Philippe Mathieu-Daudé
Add a new VIRTIO device for the virtio sound device id. Functionality
will be added in the following commits.
Signed-off-by: Emmanouil Pitsidianakis <manos.pitsidianakis@linaro.org>
---
MAINTAINERS | 6 +
hw/virtio/Kconfig | 5 +
hw/virtio/meson.build | 1 +
hw/virtio/trace-events | 9 ++
hw/virtio/virtio-snd.c | 230 +++++++++++++++++++++++++++++++++
include/hw/virtio/virtio-snd.h | 79 +++++++++++
6 files changed, 330 insertions(+)
create mode 100644 hw/virtio/virtio-snd.c
create mode 100644 include/hw/virtio/virtio-snd.h
diff --git a/MAINTAINERS b/MAINTAINERS
index 12e59b6b27..2bed60f9c1 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -2245,6 +2245,12 @@ F: hw/virtio/virtio-mem-pci.h
F: hw/virtio/virtio-mem-pci.c
F: include/hw/virtio/virtio-mem.h
+virtio-snd
+M: Manos Pitsidianakis <manos.pitsidianakis@linaro.org>
+S: Supported
+F: hw/virtio/virtio-snd*.c
+F: include/hw/virtio/virtio-snd.h
+
nvme
M: Keith Busch <kbusch@kernel.org>
M: Klaus Jensen <its@irrelevant.dk>
diff --git a/hw/virtio/Kconfig b/hw/virtio/Kconfig
index 92c9cf6c96..d6f20657b3 100644
--- a/hw/virtio/Kconfig
+++ b/hw/virtio/Kconfig
@@ -17,6 +17,11 @@ config VIRTIO_PCI
depends on PCI
select VIRTIO
+config VIRTIO_SND
+ bool
+ default y
+ depends on VIRTIO
+
config VIRTIO_MMIO
bool
select VIRTIO
diff --git a/hw/virtio/meson.build b/hw/virtio/meson.build
index 13e7c6c272..120d4bfa0a 100644
--- a/hw/virtio/meson.build
+++ b/hw/virtio/meson.build
@@ -31,6 +31,7 @@ specific_virtio_ss.add(when: 'CONFIG_VHOST_VSOCK', if_true: files('vhost-vsock.c
specific_virtio_ss.add(when: 'CONFIG_VHOST_USER_VSOCK', if_true: files('vhost-user-vsock.c'))
specific_virtio_ss.add(when: 'CONFIG_VIRTIO_RNG', if_true: files('virtio-rng.c'))
specific_virtio_ss.add(when: 'CONFIG_VIRTIO_MEM', if_true: files('virtio-mem.c'))
+specific_virtio_ss.add(when: 'CONFIG_VIRTIO_SND', if_true: files('virtio-snd.c'))
specific_virtio_ss.add(when: 'CONFIG_VHOST_USER_I2C', if_true: files('vhost-user-i2c.c'))
specific_virtio_ss.add(when: 'CONFIG_VHOST_USER_RNG', if_true: files('vhost-user-rng.c'))
specific_virtio_ss.add(when: 'CONFIG_VHOST_USER_GPIO', if_true: files('vhost-user-gpio.c'))
diff --git a/hw/virtio/trace-events b/hw/virtio/trace-events
index 7109cf1a3b..3ed7da35f2 100644
--- a/hw/virtio/trace-events
+++ b/hw/virtio/trace-events
@@ -154,3 +154,12 @@ virtio_pmem_flush_done(int type) "fsync return=%d"
virtio_gpio_start(void) "start"
virtio_gpio_stop(void) "stop"
virtio_gpio_set_status(uint8_t status) "0x%x"
+
+#virtio-snd.c
+virtio_snd_get_config(void *vdev, uint32_t jacks, uint32_t streams, uint32_t chmaps) "snd %p: get_config jacks=%"PRIu32" streams=%"PRIu32" chmaps=%"PRIu32""
+virtio_snd_set_config(void *vdev, uint32_t jacks, uint32_t new_jacks, uint32_t streams, uint32_t new_streams, uint32_t chmaps, uint32_t new_chmaps) "snd %p: set_config jacks from %"PRIu32"->%"PRIu32", streams from %"PRIu32"->%"PRIu32", chmaps from %"PRIu32"->%"PRIu32
+virtio_snd_get_features(void *vdev, uint64_t features) "snd %p: get_features 0x%"PRIx64
+virtio_snd_vm_state_running(void) "vm state running"
+virtio_snd_vm_state_stopped(void) "vm state stopped"
+virtio_snd_realize(void *snd) "snd %p: realize"
+virtio_snd_unrealize(void *snd) "snd %p: unrealize"
diff --git a/hw/virtio/virtio-snd.c b/hw/virtio/virtio-snd.c
new file mode 100644
index 0000000000..e3f2156e5e
--- /dev/null
+++ b/hw/virtio/virtio-snd.c
@@ -0,0 +1,230 @@
+/*
+ * VIRTIO Sound Device conforming to
+ *
+ * "Virtual I/O Device (VIRTIO) Version 1.2
+ * Committee Specification Draft 01
+ * 09 May 2022"
+ *
+ * <https://docs.oasis-open.org/virtio/virtio/v1.2/csd01/virtio-v1.2-csd01.html#x1-52900014>
+ *
+ * Copyright (c) 2023 Emmanouil Pitsidianakis <manos.pitsidianakis@linaro.org>
+ * Copyright (C) 2019 OpenSynergy GmbH
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or
+ * (at your option) any later version. See the COPYING file in the
+ * top-level directory.
+ */
+
+#include "qemu/osdep.h"
+#include "qemu/iov.h"
+#include "qemu/log.h"
+#include "include/qemu/lockable.h"
+#include "sysemu/runstate.h"
+#include "trace.h"
+#include "qapi/error.h"
+#include "hw/virtio/virtio-snd.h"
+
+#define VIRTIO_SOUND_VM_VERSION 1
+#define VIRTIO_SOUND_JACK_DEFAULT 0
+#define VIRTIO_SOUND_STREAM_DEFAULT 1
+#define VIRTIO_SOUND_CHMAP_DEFAULT 0
+#define VIRTIO_SOUND_HDA_FN_NID 0
+
+static const VMStateDescription vmstate_virtio_snd_device = {
+ .name = TYPE_VIRTIO_SND,
+ .version_id = VIRTIO_SOUND_VM_VERSION,
+ .minimum_version_id = VIRTIO_SOUND_VM_VERSION,
+};
+
+static const VMStateDescription vmstate_virtio_snd = {
+ .name = "virtio-sound",
+ .minimum_version_id = VIRTIO_SOUND_VM_VERSION,
+ .version_id = VIRTIO_SOUND_VM_VERSION,
+ .fields = (VMStateField[]) {
+ VMSTATE_VIRTIO_DEVICE,
+ VMSTATE_END_OF_LIST()
+ },
+};
+
+static Property virtio_snd_properties[] = {
+ DEFINE_AUDIO_PROPERTIES(VirtIOSound, card),
+ DEFINE_PROP_UINT32("jacks", VirtIOSound, snd_conf.jacks,
+ VIRTIO_SOUND_JACK_DEFAULT),
+ DEFINE_PROP_UINT32("streams", VirtIOSound, snd_conf.streams,
+ VIRTIO_SOUND_STREAM_DEFAULT),
+ DEFINE_PROP_UINT32("chmaps", VirtIOSound, snd_conf.chmaps,
+ VIRTIO_SOUND_CHMAP_DEFAULT),
+ DEFINE_PROP_END_OF_LIST(),
+};
+
+static void
+virtio_snd_get_config(VirtIODevice *vdev, uint8_t *config)
+{
+ VirtIOSound *s = VIRTIO_SND(vdev);
+ trace_virtio_snd_get_config(vdev,
+ s->snd_conf.jacks,
+ s->snd_conf.streams,
+ s->snd_conf.chmaps);
+
+ memcpy(config, &s->snd_conf, sizeof(s->snd_conf));
+}
+
+static void
+virtio_snd_set_config(VirtIODevice *vdev, const uint8_t *config)
+{
+ VirtIOSound *s = VIRTIO_SND(vdev);
+ const virtio_snd_config *sndconfig =
+ (const virtio_snd_config *)config;
+
+
+ trace_virtio_snd_set_config(vdev,
+ s->snd_conf.jacks,
+ sndconfig->jacks,
+ s->snd_conf.streams,
+ sndconfig->streams,
+ s->snd_conf.chmaps,
+ sndconfig->chmaps);
+
+ memcpy(&s->snd_conf, sndconfig, sizeof(s->snd_conf));
+}
+
+/*
+ * Queue handler stub.
+ *
+ * @vdev: VirtIOSound device
+ * @vq: virtqueue
+ */
+static void virtio_snd_handle_queue(VirtIODevice *vdev, VirtQueue *vq) {}
+
+static uint64_t get_features(VirtIODevice *vdev, uint64_t features,
+ Error **errp)
+{
+ /*
+ * virtio-v1.2-csd01, 5.14.3,
+ * Feature Bits
+ * None currently defined.
+ */
+ trace_virtio_snd_get_features(vdev, features);
+ return features | 1UL << VIRTIO_F_VERSION_1 | 1UL << VIRTIO_F_IN_ORDER;
+}
+
+static void virtio_snd_common_realize(DeviceState *dev,
+ VirtIOHandleOutput ctrl,
+ VirtIOHandleOutput evt,
+ VirtIOHandleOutput txq,
+ VirtIOHandleOutput rxq,
+ Error **errp)
+{
+ VirtIODevice *vdev = VIRTIO_DEVICE(dev);
+ VirtIOSound *vsnd = VIRTIO_SND(dev);
+
+ virtio_init(vdev, VIRTIO_ID_SOUND, sizeof(virtio_snd_config));
+
+ /* set number of jacks and streams */
+ if (vsnd->snd_conf.jacks > 8) {
+ error_setg(errp,
+ "Invalid number of jacks: %"PRIu32,
+ vsnd->snd_conf.jacks);
+ return;
+ }
+ if (vsnd->snd_conf.streams < 1 || vsnd->snd_conf.streams > 10) {
+ error_setg(errp,
+ "Invalid number of streams: %"PRIu32,
+ vsnd->snd_conf.streams);
+ return;
+ }
+
+ if (vsnd->snd_conf.chmaps > VIRTIO_SND_CHMAP_MAX_SIZE) {
+ error_setg(errp,
+ "Invalid number of channel maps: %"PRIu32,
+ vsnd->snd_conf.chmaps);
+ return;
+ }
+
+ 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)
+{
+ VirtIOSound *vsnd = VIRTIO_SND(dev);
+ Error *err = NULL;
+
+ 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,
+ &err);
+ if (err != NULL) {
+ error_propagate(errp, err);
+ return;
+ }
+}
+
+static void virtio_snd_unrealize(DeviceState *dev)
+{
+ VirtIODevice *vdev = VIRTIO_DEVICE(dev);
+ VirtIOSound *vsnd = VIRTIO_SND(dev);
+
+ qemu_del_vm_change_state_handler(vsnd->vmstate);
+ virtio_del_queue(vdev, 0);
+
+ trace_virtio_snd_unrealize(vsnd);
+
+ AUD_remove_card(&vsnd->card);
+ virtio_cleanup(vdev);
+}
+
+
+static void virtio_snd_reset(VirtIODevice *vdev) {}
+
+static void virtio_snd_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ VirtioDeviceClass *vdc = VIRTIO_DEVICE_CLASS(klass);
+
+
+ set_bit(DEVICE_CATEGORY_SOUND, dc->categories);
+ device_class_set_props(dc, virtio_snd_properties);
+
+ dc->vmsd = &vmstate_virtio_snd;
+ vdc->vmsd = &vmstate_virtio_snd_device;
+ vdc->realize = virtio_snd_realize;
+ vdc->unrealize = virtio_snd_unrealize;
+ vdc->get_config = virtio_snd_get_config;
+ vdc->set_config = virtio_snd_set_config;
+ vdc->get_features = get_features;
+ vdc->reset = virtio_snd_reset;
+ vdc->legacy_features = 0;
+}
+
+static const TypeInfo virtio_snd_types[] = {
+ {
+ .name = TYPE_VIRTIO_SND,
+ .parent = TYPE_VIRTIO_DEVICE,
+ .instance_size = sizeof(VirtIOSound),
+ .class_init = virtio_snd_class_init,
+ }
+};
+
+DEFINE_TYPES(virtio_snd_types)
diff --git a/include/hw/virtio/virtio-snd.h b/include/hw/virtio/virtio-snd.h
new file mode 100644
index 0000000000..074b66c018
--- /dev/null
+++ b/include/hw/virtio/virtio-snd.h
@@ -0,0 +1,79 @@
+/*
+ * VIRTIO Sound Device conforming to
+ *
+ * "Virtual I/O Device (VIRTIO) Version 1.2
+ * Committee Specification Draft 01
+ * 09 May 2022"
+ *
+ * Copyright (c) 2023 Emmanouil Pitsidianakis <manos.pitsidianakis@linaro.org>
+ * Copyright (C) 2019 OpenSynergy GmbH
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or
+ * (at your option) any later version. See the COPYING file in the
+ * top-level directory.
+ */
+
+#ifndef QEMU_VIRTIO_SOUND_H
+#define QEMU_VIRTIO_SOUND_H
+
+#include "hw/virtio/virtio.h"
+#include "audio/audio.h"
+#include "standard-headers/linux/virtio_ids.h"
+#include "standard-headers/linux/virtio_snd.h"
+
+#define TYPE_VIRTIO_SND "virtio-sound-device"
+#define VIRTIO_SND(obj) \
+ OBJECT_CHECK(VirtIOSound, (obj), TYPE_VIRTIO_SND)
+
+/* CONFIGURATION SPACE */
+
+typedef struct virtio_snd_config virtio_snd_config;
+
+/* COMMON DEFINITIONS */
+
+/* common header for request/response*/
+typedef struct virtio_snd_hdr virtio_snd_hdr;
+
+/* event notification */
+typedef struct virtio_snd_event virtio_snd_event;
+
+/* common control request to query an item information */
+typedef struct virtio_snd_query_info virtio_snd_query_info;
+
+/* JACK CONTROL MESSAGES */
+
+typedef struct virtio_snd_jack_hdr virtio_snd_jack_hdr;
+
+/* jack information structure */
+typedef struct virtio_snd_jack_info virtio_snd_jack_info;
+
+/* jack remapping control request */
+typedef struct virtio_snd_jack_remap virtio_snd_jack_remap;
+
+typedef struct virtio_snd_jack virtio_snd_jack;
+
+/*
+ * PCM CONTROL MESSAGES
+ */
+typedef struct virtio_snd_pcm_hdr virtio_snd_pcm_hdr;
+
+/* PCM stream info structure */
+typedef struct virtio_snd_pcm_info virtio_snd_pcm_info;
+
+/* set PCM stream params */
+typedef struct virtio_snd_pcm_set_params virtio_snd_pcm_set_params;
+
+/* I/O request header */
+typedef struct virtio_snd_pcm_xfer virtio_snd_pcm_xfer;
+
+/* I/O request status */
+typedef struct virtio_snd_pcm_status virtio_snd_pcm_status;
+
+typedef struct VirtIOSound {
+ VirtIODevice parent_obj;
+ VirtQueue *queues[VIRTIO_SND_VQ_MAX];
+ QEMUSoundCard card;
+ VMChangeStateEntry *vmstate;
+ virtio_snd_config snd_conf;
+} VirtIOSound;
+#endif
--
2.39.2
^ permalink raw reply related [flat|nested] 22+ messages in thread
* [PATCH v4 02/12] Add virtio-sound-pci device
2023-07-20 12:57 [PATCH v4 00/12] Add VIRTIO sound card Emmanouil Pitsidianakis
2023-07-20 12:57 ` [PATCH v4 01/12] Add virtio-sound device stub Emmanouil Pitsidianakis
@ 2023-07-20 12:57 ` Emmanouil Pitsidianakis
2023-07-20 12:57 ` [PATCH v4 03/12] virtio-sound: handle control messages and streams Emmanouil Pitsidianakis
` (9 subsequent siblings)
11 siblings, 0 replies; 22+ messages in thread
From: Emmanouil Pitsidianakis @ 2023-07-20 12:57 UTC (permalink / raw)
To: qemu-devel
Cc: Emmanouil Pitsidianakis, Igor Skalkin, Anton Yakovlev,
Paolo Bonzini, Gerd Hoffmann, Michael S. Tsirkin,
Marcel Apfelbaum, Daniel P. Berrangé, Eduardo Habkost,
Marc-André Lureau, Volker Rümelin,
Kővágó, Zoltán, Alex Bennee,
Philippe Mathieu-Daudé
This patch adds a PCI wrapper device for the virtio-sound device.
It is necessary to instantiate a virtio-snd device in a guest.
All sound logic will be added to the virtio-snd device in the following
commits.
To add this device with a guest, you'll need a >=5.13 kernel compiled
with CONFIG_SND_VIRTIO=y, which at the time of writing most distros have
off by default.
Use with following flags in the invocation:
-device virtio-sound-pci,disable-legacy=on
And an audio backend listed with `-audio driver=help` that works on
your host machine, e.g.:
Pulseaudio:
-audio driver=pa,model=virtio-sound
or
-audio driver=pa,model=virtio-sound,server=/run/user/1000/pulse/native
sdl:
-audio driver=sdl,model=virtio-sound
coreaudio (macos/darwin):
-audio driver=coreaudio,model=virtio-sound
etc.
Signed-off-by: Emmanouil Pitsidianakis <manos.pitsidianakis@linaro.org>
---
hw/virtio/meson.build | 1 +
hw/virtio/virtio-snd-pci.c | 91 ++++++++++++++++++++++++++++++++++++++
include/hw/pci/pci.h | 1 +
softmmu/qdev-monitor.c | 1 +
4 files changed, 94 insertions(+)
create mode 100644 hw/virtio/virtio-snd-pci.c
diff --git a/hw/virtio/meson.build b/hw/virtio/meson.build
index 120d4bfa0a..5e5a83a4ee 100644
--- a/hw/virtio/meson.build
+++ b/hw/virtio/meson.build
@@ -63,6 +63,7 @@ virtio_pci_ss.add(when: 'CONFIG_VIRTIO_SERIAL', if_true: files('virtio-serial-pc
virtio_pci_ss.add(when: 'CONFIG_VIRTIO_PMEM', if_true: files('virtio-pmem-pci.c'))
virtio_pci_ss.add(when: 'CONFIG_VIRTIO_IOMMU', if_true: files('virtio-iommu-pci.c'))
virtio_pci_ss.add(when: 'CONFIG_VIRTIO_MEM', if_true: files('virtio-mem-pci.c'))
+virtio_pci_ss.add(when: 'CONFIG_VIRTIO_SND', if_true: files('virtio-snd-pci.c'))
virtio_pci_ss.add(when: 'CONFIG_VHOST_VDPA_DEV', if_true: files('vdpa-dev-pci.c'))
virtio_pci_ss.add(when: 'CONFIG_VIRTIO_MD', if_true: files('virtio-md-pci.c'))
diff --git a/hw/virtio/virtio-snd-pci.c b/hw/virtio/virtio-snd-pci.c
new file mode 100644
index 0000000000..53070b85f6
--- /dev/null
+++ b/hw/virtio/virtio-snd-pci.c
@@ -0,0 +1,91 @@
+/*
+ * VIRTIO Sound Device PCI Bindings
+ *
+ * Copyright (c) 2023 Emmanouil Pitsidianakis <manos.pitsidianakis@linaro.org>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or
+ * (at your option) any later version. See the COPYING file in the
+ * top-level directory.
+ */
+
+#include "qemu/osdep.h"
+#include "hw/audio/soundhw.h"
+#include "hw/virtio/virtio-pci.h"
+#include "hw/virtio/virtio-snd.h"
+
+typedef struct VirtIOSoundPCI VirtIOSoundPCI;
+
+/*
+ * virtio-snd-pci: This extends VirtioPCIProxy.
+ */
+#define TYPE_VIRTIO_SND_PCI "virtio-sound-pci-base"
+DECLARE_INSTANCE_CHECKER(VirtIOSoundPCI, VIRTIO_SOUND_PCI,
+ TYPE_VIRTIO_SND_PCI)
+
+struct VirtIOSoundPCI {
+ VirtIOPCIProxy parent;
+ VirtIOSound vdev;
+};
+
+static Property virtio_snd_pci_properties[] = {
+ DEFINE_PROP_END_OF_LIST(),
+};
+
+static const char *audiodev_id;
+
+static int virtio_snd_init_pci(PCIBus *init_bus, const char *audiodev)
+{
+ audiodev_id = audiodev;
+ return 0;
+}
+
+static void virtio_snd_pci_realize(VirtIOPCIProxy *vpci_dev, Error **errp)
+{
+ VirtIOSoundPCI *dev = VIRTIO_SOUND_PCI(vpci_dev);
+ DeviceState *vdev = DEVICE(&dev->vdev);
+
+ qdev_set_parent_bus(vdev, BUS(&vpci_dev->bus), errp);
+ qdev_prop_set_string(vdev, "audiodev", audiodev_id);
+ object_property_set_bool(OBJECT(vdev), "realized", true, errp);
+}
+
+static void virtio_snd_pci_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ VirtioPCIClass *vpciklass = VIRTIO_PCI_CLASS(klass);
+ PCIDeviceClass *pcidev_k = PCI_DEVICE_CLASS(klass);
+
+ vpciklass->realize = virtio_snd_pci_realize;
+ set_bit(DEVICE_CATEGORY_SOUND, dc->categories);
+
+ pcidev_k->vendor_id = PCI_VENDOR_ID_REDHAT_QUMRANET;
+ pcidev_k->device_id = PCI_DEVICE_ID_VIRTIO_SND;
+ pcidev_k->revision = VIRTIO_PCI_ABI_VERSION;
+ pcidev_k->class_id = PCI_CLASS_MULTIMEDIA_AUDIO;
+ device_class_set_props(dc, virtio_snd_pci_properties);
+}
+
+static void virtio_snd_pci_instance_init(Object *obj)
+{
+ VirtIOSoundPCI *dev = VIRTIO_SOUND_PCI(obj);
+
+ virtio_instance_init_common(obj, &dev->vdev, sizeof(dev->vdev),
+ TYPE_VIRTIO_SND);
+}
+
+static const VirtioPCIDeviceTypeInfo virtio_snd_pci_info = {
+ .base_name = TYPE_VIRTIO_SND_PCI,
+ .generic_name = "virtio-sound-pci",
+ .instance_size = sizeof(VirtIOSoundPCI),
+ .instance_init = virtio_snd_pci_instance_init,
+ .class_init = virtio_snd_pci_class_init,
+};
+
+static void virtio_snd_pci_register(void)
+{
+ virtio_pci_types_register(&virtio_snd_pci_info);
+ pci_register_soundhw("virtio-sound", "Virtio Sound Device",
+ virtio_snd_init_pci);
+}
+
+type_init(virtio_snd_pci_register);
diff --git a/include/hw/pci/pci.h b/include/hw/pci/pci.h
index abdc1ef103..3cd5712035 100644
--- a/include/hw/pci/pci.h
+++ b/include/hw/pci/pci.h
@@ -85,6 +85,7 @@ extern bool pci_available;
#define PCI_DEVICE_ID_VIRTIO_RNG 0x1005
#define PCI_DEVICE_ID_VIRTIO_9P 0x1009
#define PCI_DEVICE_ID_VIRTIO_VSOCK 0x1012
+#define PCI_DEVICE_ID_VIRTIO_SND 0x1019
/*
* modern virtio-pci devices get their id assigned automatically,
diff --git a/softmmu/qdev-monitor.c b/softmmu/qdev-monitor.c
index 74f4e41338..2e9835ad88 100644
--- a/softmmu/qdev-monitor.c
+++ b/softmmu/qdev-monitor.c
@@ -108,6 +108,7 @@ static const QDevAlias qdev_alias_table[] = {
{ "virtio-serial-device", "virtio-serial", QEMU_ARCH_VIRTIO_MMIO },
{ "virtio-serial-ccw", "virtio-serial", QEMU_ARCH_VIRTIO_CCW },
{ "virtio-serial-pci", "virtio-serial", QEMU_ARCH_VIRTIO_PCI},
+ { "virtio-sound-pci", "virtio-sound", QEMU_ARCH_VIRTIO_PCI},
{ "virtio-tablet-device", "virtio-tablet", QEMU_ARCH_VIRTIO_MMIO },
{ "virtio-tablet-ccw", "virtio-tablet", QEMU_ARCH_VIRTIO_CCW },
{ "virtio-tablet-pci", "virtio-tablet", QEMU_ARCH_VIRTIO_PCI },
--
2.39.2
^ permalink raw reply related [flat|nested] 22+ messages in thread
* [PATCH v4 03/12] virtio-sound: handle control messages and streams
2023-07-20 12:57 [PATCH v4 00/12] Add VIRTIO sound card Emmanouil Pitsidianakis
2023-07-20 12:57 ` [PATCH v4 01/12] Add virtio-sound device stub Emmanouil Pitsidianakis
2023-07-20 12:57 ` [PATCH v4 02/12] Add virtio-sound-pci device Emmanouil Pitsidianakis
@ 2023-07-20 12:57 ` Emmanouil Pitsidianakis
2023-07-20 12:57 ` [PATCH v4 04/12] virtio-sound: set PCM stream parameters Emmanouil Pitsidianakis
` (8 subsequent siblings)
11 siblings, 0 replies; 22+ messages in thread
From: Emmanouil Pitsidianakis @ 2023-07-20 12:57 UTC (permalink / raw)
To: qemu-devel
Cc: Emmanouil Pitsidianakis, Igor Skalkin, Anton Yakovlev,
Paolo Bonzini, Gerd Hoffmann, Michael S. Tsirkin,
Marcel Apfelbaum, Daniel P. Berrangé, Eduardo Habkost,
Marc-André Lureau, Volker Rümelin,
Kővágó, Zoltán, Alex Bennee,
Philippe Mathieu-Daudé
Receive guest requests in the control (CTRL) queue of the virtio sound
device and reply with a NOT SUPPORTED error to all control commands.
The receiving handler is virtio_snd_handle_ctrl(). It stores all control
messages in the queue in the device's command queue. Then it calls
virtio_snd_process_cmdq() to handle each message.
The handler is process_cmd() which replies with VIRTIO_SND_S_NOT_SUPP.
Signed-off-by: Emmanouil Pitsidianakis <manos.pitsidianakis@linaro.org>
---
hw/virtio/trace-events | 4 +
hw/virtio/virtio-snd.c | 222 +++++++++++++++++++++++++++++++--
include/hw/virtio/virtio-snd.h | 71 ++++++++++-
3 files changed, 287 insertions(+), 10 deletions(-)
diff --git a/hw/virtio/trace-events b/hw/virtio/trace-events
index 3ed7da35f2..8a223e36e9 100644
--- a/hw/virtio/trace-events
+++ b/hw/virtio/trace-events
@@ -163,3 +163,7 @@ virtio_snd_vm_state_running(void) "vm state running"
virtio_snd_vm_state_stopped(void) "vm state stopped"
virtio_snd_realize(void *snd) "snd %p: realize"
virtio_snd_unrealize(void *snd) "snd %p: unrealize"
+virtio_snd_handle_ctrl(void *vdev, void *vq) "snd %p: handle ctrl event for queue %p"
+virtio_snd_handle_code(uint32_t val, const char *code) "ctrl code msg val = %"PRIu32" == %s"
+virtio_snd_handle_chmap_info(void) "VIRTIO_SND_CHMAP_INFO called"
+virtio_snd_handle_event(void) "event queue callback called"
diff --git a/hw/virtio/virtio-snd.c b/hw/virtio/virtio-snd.c
index e3f2156e5e..5a0c2c7594 100644
--- a/hw/virtio/virtio-snd.c
+++ b/hw/virtio/virtio-snd.c
@@ -30,6 +30,29 @@
#define VIRTIO_SOUND_CHMAP_DEFAULT 0
#define VIRTIO_SOUND_HDA_FN_NID 0
+static const char *print_code(uint32_t code)
+{
+ #define CASE(CODE) \
+ case VIRTIO_SND_R_##CODE: \
+ return "VIRTIO_SND_R_"#CODE
+
+ switch (code) {
+ CASE(JACK_INFO);
+ CASE(JACK_REMAP);
+ CASE(PCM_INFO);
+ CASE(PCM_SET_PARAMS);
+ CASE(PCM_PREPARE);
+ CASE(PCM_RELEASE);
+ CASE(PCM_START);
+ CASE(PCM_STOP);
+ CASE(CHMAP_INFO);
+ default:
+ return "invalid code";
+ }
+
+ #undef CASE
+};
+
static const VMStateDescription vmstate_virtio_snd_device = {
.name = TYPE_VIRTIO_SND,
.version_id = VIRTIO_SOUND_VM_VERSION,
@@ -89,12 +112,148 @@ virtio_snd_set_config(VirtIODevice *vdev, const uint8_t *config)
}
/*
- * Queue handler stub.
+ * The actual processing done in virtio_snd_process_cmdq().
+ *
+ * @s: VirtIOSound device
+ * @cmd: control command request
+ */
+static inline void
+process_cmd(VirtIOSound *s, virtio_snd_ctrl_command *cmd)
+{
+ size_t sz = iov_to_buf(cmd->elem->out_sg,
+ cmd->elem->out_num,
+ 0,
+ &cmd->ctrl,
+ sizeof(cmd->ctrl));
+ if (sz != sizeof(cmd->ctrl)) {
+ qemu_log_mask(LOG_GUEST_ERROR,
+ "%s: virtio-snd command size incorrect %zu vs \
+ %zu\n", __func__, sz, sizeof(cmd->ctrl));
+ return;
+ }
+
+ trace_virtio_snd_handle_code(cmd->ctrl.code,
+ print_code(cmd->ctrl.code));
+
+ switch (cmd->ctrl.code) {
+ case VIRTIO_SND_R_JACK_INFO:
+ case VIRTIO_SND_R_JACK_REMAP:
+ qemu_log_mask(LOG_UNIMP,
+ "virtio_snd: jack functionality is unimplemented.");
+ cmd->resp.code = VIRTIO_SND_S_NOT_SUPP;
+ break;
+ case VIRTIO_SND_R_PCM_INFO:
+ case VIRTIO_SND_R_PCM_SET_PARAMS:
+ case VIRTIO_SND_R_PCM_PREPARE:
+ case VIRTIO_SND_R_PCM_START:
+ case VIRTIO_SND_R_PCM_STOP:
+ case VIRTIO_SND_R_PCM_RELEASE:
+ cmd->resp.code = VIRTIO_SND_S_NOT_SUPP;
+ break;
+ case VIRTIO_SND_R_CHMAP_INFO:
+ qemu_log_mask(LOG_UNIMP,
+ "virtio_snd: chmap info functionality is unimplemented.");
+ trace_virtio_snd_handle_chmap_info();
+ cmd->resp.code = VIRTIO_SND_S_NOT_SUPP;
+ break;
+ default:
+ /* error */
+ error_report("virtio snd header not recognized: %"PRIu32,
+ cmd->ctrl.code);
+ cmd->resp.code = VIRTIO_SND_S_BAD_MSG;
+ }
+
+ iov_from_buf(cmd->elem->in_sg,
+ cmd->elem->in_num,
+ 0,
+ &cmd->resp,
+ sizeof(cmd->resp));
+ virtqueue_push(cmd->vq, cmd->elem, sizeof(cmd->elem));
+ virtio_notify(VIRTIO_DEVICE(s), cmd->vq);
+}
+
+/*
+ * Consume all elements in command queue.
+ *
+ * @s: VirtIOSound device
+ */
+static void virtio_snd_process_cmdq(VirtIOSound *s)
+{
+ virtio_snd_ctrl_command *cmd;
+
+ if (unlikely(qatomic_read(&s->processing_cmdq))) {
+ return;
+ }
+
+ WITH_QEMU_LOCK_GUARD(&s->cmdq_mutex) {
+ qatomic_set(&s->processing_cmdq, true);
+ while (!QTAILQ_EMPTY(&s->cmdq)) {
+ cmd = QTAILQ_FIRST(&s->cmdq);
+
+ /* process command */
+ process_cmd(s, cmd);
+
+ QTAILQ_REMOVE(&s->cmdq, cmd, next);
+
+ g_free(cmd);
+ }
+ qatomic_set(&s->processing_cmdq, false);
+ }
+}
+
+/*
+ * The control message handler. Pops an element from the control virtqueue,
+ * and stores them to VirtIOSound's cmdq queue and finally calls
+ * virtio_snd_process_cmdq() for processing.
+ *
+ * @vdev: VirtIOSound device
+ * @vq: Control virtqueue
+ */
+static void virtio_snd_handle_ctrl(VirtIODevice *vdev, VirtQueue *vq)
+{
+ VirtIOSound *s = VIRTIO_SND(vdev);
+ VirtQueueElement *elem;
+ virtio_snd_ctrl_command *cmd;
+
+ trace_virtio_snd_handle_ctrl(vdev, vq);
+
+ if (!virtio_queue_ready(vq)) {
+ return;
+ }
+
+ elem = virtqueue_pop(vq, sizeof(VirtQueueElement));
+ while (elem) {
+ cmd = g_new0(virtio_snd_ctrl_command, 1);
+ cmd->elem = elem;
+ cmd->vq = vq;
+ cmd->resp.code = VIRTIO_SND_S_OK;
+ QTAILQ_INSERT_TAIL(&s->cmdq, cmd, next);
+ elem = virtqueue_pop(vq, sizeof(VirtQueueElement));
+ }
+
+ virtio_snd_process_cmdq(s);
+}
+
+/*
+ * The event virtqueue handler.
+ * Not implemented yet.
+ *
+ * @vdev: VirtIOSound device
+ * @vq: event vq
+ */
+static void virtio_snd_handle_event(VirtIODevice *vdev, VirtQueue *vq)
+{
+ qemu_log_mask(LOG_UNIMP, "virtio_snd: event queue is unimplemented.");
+ trace_virtio_snd_handle_event();
+}
+
+/*
+ * Stub buffer virtqueue handler.
*
* @vdev: VirtIOSound device
* @vq: virtqueue
*/
-static void virtio_snd_handle_queue(VirtIODevice *vdev, VirtQueue *vq) {}
+static void virtio_snd_handle_xfer(VirtIODevice *vdev, VirtQueue *vq) {}
static uint64_t get_features(VirtIODevice *vdev, uint64_t features,
Error **errp)
@@ -108,6 +267,20 @@ static uint64_t get_features(VirtIODevice *vdev, uint64_t features,
return features | 1UL << VIRTIO_F_VERSION_1 | 1UL << VIRTIO_F_IN_ORDER;
}
+static void virtio_snd_set_pcm(VirtIOSound *snd)
+{
+ VirtIOSoundPCM *pcm;
+
+ pcm = g_new0(VirtIOSoundPCM, 1);
+ pcm->snd = snd;
+
+ pcm->streams = g_new0(VirtIOSoundPCMStream *, snd->snd_conf.streams);
+ pcm->pcm_params = g_new0(VirtIOSoundPCMParams *, snd->snd_conf.streams);
+ pcm->jacks = g_new0(virtio_snd_jack *, snd->snd_conf.jacks);
+
+ snd->pcm = pcm;
+}
+
static void virtio_snd_common_realize(DeviceState *dev,
VirtIOHandleOutput ctrl,
VirtIOHandleOutput evt,
@@ -118,6 +291,8 @@ 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));
/* set number of jacks and streams */
@@ -147,6 +322,8 @@ 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
@@ -164,39 +341,68 @@ static void virtio_snd_realize(DeviceState *dev, Error **errp)
VirtIOSound *vsnd = VIRTIO_SND(dev);
Error *err = NULL;
+ vsnd->pcm = NULL;
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,
+ virtio_snd_handle_ctrl,
+ virtio_snd_handle_event,
+ virtio_snd_handle_xfer,
+ virtio_snd_handle_xfer,
&err);
if (err != NULL) {
error_propagate(errp, err);
- return;
}
}
+/*
+ * Close the sound card.
+ *
+ * @stream: VirtIOSoundPCMStream *stream
+ */
+static void virtio_snd_pcm_close(VirtIOSoundPCMStream *stream)
+{
+ virtio_snd_process_cmdq(stream->s);
+}
+
static void virtio_snd_unrealize(DeviceState *dev)
{
VirtIODevice *vdev = VIRTIO_DEVICE(dev);
VirtIOSound *vsnd = VIRTIO_SND(dev);
+ VirtIOSoundPCMStream *stream;
qemu_del_vm_change_state_handler(vsnd->vmstate);
virtio_del_queue(vdev, 0);
trace_virtio_snd_unrealize(vsnd);
+ for (uint32_t i = 0; i < vsnd->snd_conf.streams; i++) {
+ stream = vsnd->pcm->streams[i];
+ virtio_snd_pcm_close(stream);
+ g_free(stream);
+ }
AUD_remove_card(&vsnd->card);
+ g_free(vsnd->pcm);
virtio_cleanup(vdev);
}
-static void virtio_snd_reset(VirtIODevice *vdev) {}
+static void virtio_snd_reset(VirtIODevice *vdev)
+{
+ VirtIOSound *s = VIRTIO_SND(vdev);
+ virtio_snd_ctrl_command *cmd;
+
+ WITH_QEMU_LOCK_GUARD(&s->cmdq_mutex) {
+ while (!QTAILQ_EMPTY(&s->cmdq)) {
+ cmd = QTAILQ_FIRST(&s->cmdq);
+ QTAILQ_REMOVE(&s->cmdq, cmd, next);
+ g_free(cmd);
+ }
+ }
+}
static void virtio_snd_class_init(ObjectClass *klass, void *data)
{
diff --git a/include/hw/virtio/virtio-snd.h b/include/hw/virtio/virtio-snd.h
index 074b66c018..1a9835841d 100644
--- a/include/hw/virtio/virtio-snd.h
+++ b/include/hw/virtio/virtio-snd.h
@@ -69,11 +69,78 @@ typedef struct virtio_snd_pcm_xfer virtio_snd_pcm_xfer;
/* I/O request status */
typedef struct virtio_snd_pcm_status virtio_snd_pcm_status;
-typedef struct VirtIOSound {
+/* device structs */
+
+typedef struct VirtIOSound VirtIOSound;
+
+typedef struct VirtIOSoundPCMStream VirtIOSoundPCMStream;
+
+typedef struct virtio_snd_ctrl_command virtio_snd_ctrl_command;
+
+typedef struct VirtIOSoundPCMParams VirtIOSoundPCMParams;
+
+typedef struct VirtIOSoundPCM VirtIOSoundPCM;
+
+/* Stream params */
+struct VirtIOSoundPCMParams {
+ uint32_t features;
+ uint32_t buffer_bytes; /* size of hardware buffer in bytes */
+ uint32_t period_bytes; /* size of hardware period in bytes */
+ uint8_t channels;
+ uint8_t format;
+ uint8_t rate;
+};
+
+struct VirtIOSoundPCM {
+ VirtIOSound *snd;
+ VirtIOSoundPCMParams **pcm_params;
+ VirtIOSoundPCMStream **streams;
+ virtio_snd_jack **jacks;
+};
+
+struct VirtIOSoundPCMStream {
+ VirtIOSoundPCM *pcm;
+ virtio_snd_pcm_info info;
+ uint32_t id;
+ uint32_t buffer_bytes;
+ uint32_t period_bytes;
+ /* channel position values (VIRTIO_SND_CHMAP_XXX) */
+ uint8_t positions[VIRTIO_SND_CHMAP_MAX_SIZE];
+ VirtIOSound *s;
+ uint32_t features; /* 1 << VIRTIO_SND_PCM_F_XXX */
+ uint64_t formats; /* 1 << VIRTIO_SND_PCM_FMT_XXX */
+ uint64_t rates; /* 1 << VIRTIO_SND_PCM_RATE_XXX */
+ uint8_t direction;
+ uint8_t channels_min;
+ uint8_t channels_max;
+ bool flushing;
+ audsettings as;
+ audsettings desired_as;
+ union {
+ SWVoiceIn *in;
+ SWVoiceOut *out;
+ } voice;
+ QemuMutex queue_mutex;
+ QSIMPLEQ_HEAD(, VirtIOSoundPCMBlock) queue;
+};
+
+struct VirtIOSound {
VirtIODevice parent_obj;
VirtQueue *queues[VIRTIO_SND_VQ_MAX];
+ VirtIOSoundPCM *pcm;
QEMUSoundCard card;
VMChangeStateEntry *vmstate;
virtio_snd_config snd_conf;
-} VirtIOSound;
+ QemuMutex cmdq_mutex;
+ QTAILQ_HEAD(, virtio_snd_ctrl_command) cmdq;
+ bool processing_cmdq;
+};
+
+struct virtio_snd_ctrl_command {
+ VirtQueueElement *elem;
+ VirtQueue *vq;
+ virtio_snd_hdr ctrl;
+ virtio_snd_hdr resp;
+ QTAILQ_ENTRY(virtio_snd_ctrl_command) next;
+};
#endif
--
2.39.2
^ permalink raw reply related [flat|nested] 22+ messages in thread
* [PATCH v4 04/12] virtio-sound: set PCM stream parameters
2023-07-20 12:57 [PATCH v4 00/12] Add VIRTIO sound card Emmanouil Pitsidianakis
` (2 preceding siblings ...)
2023-07-20 12:57 ` [PATCH v4 03/12] virtio-sound: handle control messages and streams Emmanouil Pitsidianakis
@ 2023-07-20 12:57 ` Emmanouil Pitsidianakis
2023-07-20 12:57 ` [PATCH v4 05/12] virtio-sound: prepare PCM streams Emmanouil Pitsidianakis
` (7 subsequent siblings)
11 siblings, 0 replies; 22+ messages in thread
From: Emmanouil Pitsidianakis @ 2023-07-20 12:57 UTC (permalink / raw)
To: qemu-devel
Cc: Emmanouil Pitsidianakis, Igor Skalkin, Anton Yakovlev,
Paolo Bonzini, Gerd Hoffmann, Michael S. Tsirkin,
Marcel Apfelbaum, Daniel P. Berrangé, Eduardo Habkost,
Marc-André Lureau, Volker Rümelin,
Kővágó, Zoltán, Alex Bennee,
Philippe Mathieu-Daudé
This commit sets the virtio-snd device's default PCM parameters in
virtio_snd_pcm_set_params_impl(). The same function will be used to set
parameters from the guest with VIRTIO_SND_R_PCM_SET_PARAMS in a
follow-up commit.
PCM parameters describe the sound card parameters that the guest's
kernel sees as an ALSA device.
Signed-off-by: Emmanouil Pitsidianakis <manos.pitsidianakis@linaro.org>
---
hw/virtio/virtio-snd.c | 109 +++++++++++++++++++++++++++++++++++++++++
1 file changed, 109 insertions(+)
diff --git a/hw/virtio/virtio-snd.c b/hw/virtio/virtio-snd.c
index 5a0c2c7594..62d9bf557c 100644
--- a/hw/virtio/virtio-snd.c
+++ b/hw/virtio/virtio-snd.c
@@ -30,6 +30,29 @@
#define VIRTIO_SOUND_CHMAP_DEFAULT 0
#define VIRTIO_SOUND_HDA_FN_NID 0
+static uint32_t supported_formats = BIT(VIRTIO_SND_PCM_FMT_S8)
+ | BIT(VIRTIO_SND_PCM_FMT_U8)
+ | BIT(VIRTIO_SND_PCM_FMT_S16)
+ | BIT(VIRTIO_SND_PCM_FMT_U16)
+ | BIT(VIRTIO_SND_PCM_FMT_S32)
+ | BIT(VIRTIO_SND_PCM_FMT_U32)
+ | BIT(VIRTIO_SND_PCM_FMT_FLOAT);
+
+static uint32_t supported_rates = BIT(VIRTIO_SND_PCM_RATE_5512)
+ | BIT(VIRTIO_SND_PCM_RATE_8000)
+ | BIT(VIRTIO_SND_PCM_RATE_11025)
+ | BIT(VIRTIO_SND_PCM_RATE_16000)
+ | BIT(VIRTIO_SND_PCM_RATE_22050)
+ | BIT(VIRTIO_SND_PCM_RATE_32000)
+ | BIT(VIRTIO_SND_PCM_RATE_44100)
+ | BIT(VIRTIO_SND_PCM_RATE_48000)
+ | BIT(VIRTIO_SND_PCM_RATE_64000)
+ | BIT(VIRTIO_SND_PCM_RATE_88200)
+ | BIT(VIRTIO_SND_PCM_RATE_96000)
+ | BIT(VIRTIO_SND_PCM_RATE_176400)
+ | BIT(VIRTIO_SND_PCM_RATE_192000)
+ | BIT(VIRTIO_SND_PCM_RATE_384000);
+
static const char *print_code(uint32_t code)
{
#define CASE(CODE) \
@@ -111,6 +134,72 @@ virtio_snd_set_config(VirtIODevice *vdev, const uint8_t *config)
memcpy(&s->snd_conf, sndconfig, sizeof(s->snd_conf));
}
+/*
+ * Get params for a specific stream.
+ *
+ * @s: VirtIOSound device
+ * @stream_id: stream id
+ */
+static VirtIOSoundPCMParams *virtio_snd_pcm_get_params(VirtIOSound *s,
+ uint32_t stream_id)
+{
+ return stream_id >= s->snd_conf.streams ? NULL
+ : s->pcm->pcm_params[stream_id];
+}
+
+/*
+ * Set the given stream params.
+ * Called by both virtio_snd_handle_pcm_set_params and during device
+ * initialization.
+ * Returns the response status code. (VIRTIO_SND_S_*).
+ *
+ * @s: VirtIOSound device
+ * @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)
+{
+ VirtIOSoundPCMParams *st_params;
+ uint32_t stream_id = params->hdr.stream_id;
+
+ if (stream_id > s->snd_conf.streams || !(s->pcm->pcm_params)) {
+ virtio_error(VIRTIO_DEVICE(s), "Streams have not been initialized.\n");
+ return VIRTIO_SND_S_BAD_MSG;
+ }
+
+ if (!s->pcm->pcm_params[stream_id]) {
+ s->pcm->pcm_params[stream_id] = g_new0(VirtIOSoundPCMParams, 1);
+ }
+ st_params = virtio_snd_pcm_get_params(s, stream_id);
+
+ st_params->features = params->features;
+ st_params->buffer_bytes = params->buffer_bytes;
+ st_params->period_bytes = params->period_bytes;
+
+ if (params->channels < 1 || params->channels > AUDIO_MAX_CHANNELS) {
+ error_report("Number of channels is not supported.");
+ return VIRTIO_SND_S_NOT_SUPP;
+ }
+ st_params->channels = params->channels;
+
+ if (!(supported_formats & BIT(params->format))) {
+ error_report("Stream format is not supported.");
+ return VIRTIO_SND_S_NOT_SUPP;
+ }
+ st_params->format = params->format;
+
+ if (!(supported_rates & BIT(params->rate))) {
+ error_report("Stream rate is not supported.");
+ return VIRTIO_SND_S_NOT_SUPP;
+ }
+ st_params->rate = params->rate;
+ st_params->period_bytes = params->period_bytes;
+ st_params->buffer_bytes = params->buffer_bytes;
+
+ return VIRTIO_SND_S_OK;
+}
+
/*
* The actual processing done in virtio_snd_process_cmdq().
*
@@ -290,6 +379,8 @@ static void virtio_snd_common_realize(DeviceState *dev,
{
VirtIODevice *vdev = VIRTIO_DEVICE(dev);
VirtIOSound *vsnd = VIRTIO_SND(dev);
+ virtio_snd_pcm_set_params default_params;
+ uint32_t status;
virtio_snd_set_pcm(vsnd);
@@ -318,12 +409,30 @@ static void virtio_snd_common_realize(DeviceState *dev,
AUD_register_card("virtio-sound", &vsnd->card);
+ /* set default params for all streams */
+ default_params.features = 0;
+ default_params.buffer_bytes = 8192;
+ default_params.period_bytes = 4096;
+ default_params.channels = 2;
+ default_params.format = VIRTIO_SND_PCM_FMT_S16;
+ default_params.rate = VIRTIO_SND_PCM_RATE_44100;
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);
qemu_mutex_init(&vsnd->cmdq_mutex);
QTAILQ_INIT(&vsnd->cmdq);
+
+ 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);
+ if (status != VIRTIO_SND_S_OK) {
+ error_setg(errp,
+ "Can't initalize stream params, device responded with %s.",
+ print_code(status));
+ return;
+ }
+ }
}
static void
--
2.39.2
^ permalink raw reply related [flat|nested] 22+ messages in thread
* [PATCH v4 05/12] virtio-sound: prepare PCM streams
2023-07-20 12:57 [PATCH v4 00/12] Add VIRTIO sound card Emmanouil Pitsidianakis
` (3 preceding siblings ...)
2023-07-20 12:57 ` [PATCH v4 04/12] virtio-sound: set PCM stream parameters Emmanouil Pitsidianakis
@ 2023-07-20 12:57 ` Emmanouil Pitsidianakis
2023-07-25 13:38 ` Marc-André Lureau
2023-07-20 12:57 ` [PATCH v4 06/12] virtio-sound: handle VIRTIO_SND_R_PCM_INFO request Emmanouil Pitsidianakis
` (6 subsequent siblings)
11 siblings, 1 reply; 22+ messages in thread
From: Emmanouil Pitsidianakis @ 2023-07-20 12:57 UTC (permalink / raw)
To: qemu-devel
Cc: Emmanouil Pitsidianakis, Igor Skalkin, Anton Yakovlev,
Paolo Bonzini, Gerd Hoffmann, Michael S. Tsirkin,
Marcel Apfelbaum, Daniel P. Berrangé, Eduardo Habkost,
Marc-André Lureau, Volker Rümelin,
Kővágó, Zoltán, Alex Bennee,
Philippe Mathieu-Daudé
After setting PCM parameters, instantiate ("prepare") each stream in
virtio_snd_pcm_prepare_impl().
Signed-off-by: Emmanouil Pitsidianakis <manos.pitsidianakis@linaro.org>
---
hw/virtio/virtio-snd.c | 133 +++++++++++++++++++++++++++++++++++++++++
1 file changed, 133 insertions(+)
diff --git a/hw/virtio/virtio-snd.c b/hw/virtio/virtio-snd.c
index 62d9bf557c..ca09c937c7 100644
--- a/hw/virtio/virtio-snd.c
+++ b/hw/virtio/virtio-snd.c
@@ -200,6 +200,132 @@ uint32_t virtio_snd_pcm_set_params_impl(VirtIOSound *s,
return VIRTIO_SND_S_OK;
}
+/*
+ * Get a QEMU Audiosystem compatible format value from a VIRTIO_SND_PCM_FMT_*
+ */
+static AudioFormat virtio_snd_get_qemu_format(uint32_t format)
+{
+ #define CASE(FMT) \
+ case VIRTIO_SND_PCM_FMT_##FMT: \
+ return AUDIO_FORMAT_##FMT;
+
+ switch (format) {
+ CASE(U8)
+ CASE(S8)
+ CASE(U16)
+ CASE(S16)
+ CASE(U32)
+ CASE(S32)
+ case VIRTIO_SND_PCM_FMT_FLOAT:
+ return AUDIO_FORMAT_F32;
+ default:
+ g_assert_not_reached();
+ }
+
+ #undef CASE
+}
+
+/*
+ * Get a QEMU Audiosystem compatible frequency value from a
+ * VIRTIO_SND_PCM_RATE_*
+ */
+static uint32_t virtio_snd_get_qemu_freq(uint32_t rate)
+{
+ #define CASE(RATE) \
+ case VIRTIO_SND_PCM_RATE_##RATE: \
+ return RATE;
+
+ switch (rate) {
+ CASE(5512)
+ CASE(8000)
+ CASE(11025)
+ CASE(16000)
+ CASE(22050)
+ CASE(32000)
+ CASE(44100)
+ CASE(48000)
+ CASE(64000)
+ CASE(88200)
+ CASE(96000)
+ CASE(176400)
+ CASE(192000)
+ CASE(384000)
+ default:
+ g_assert_not_reached();
+ }
+
+ #undef CASE
+}
+
+/*
+ * Get QEMU Audiosystem compatible audsettings from virtio based pcm stream
+ * params.
+ */
+static void virtio_snd_get_qemu_audsettings(audsettings *as,
+ VirtIOSoundPCMParams *params)
+{
+ as->nchannels = MIN(AUDIO_MAX_CHANNELS, params->channels);
+ as->fmt = virtio_snd_get_qemu_format(params->format);
+ as->freq = virtio_snd_get_qemu_freq(params->rate);
+ as->endianness = AUDIO_HOST_ENDIANNESS;
+}
+
+/*
+ * Prepares a VirtIOSound card stream.
+ * Returns the response status code. (VIRTIO_SND_S_*).
+ *
+ * @s: VirtIOSound device
+ * @stream_id: stream id
+ */
+static uint32_t virtio_snd_pcm_prepare_impl(VirtIOSound *s, uint32_t stream_id)
+{
+ audsettings as;
+ VirtIOSoundPCMParams *params;
+ VirtIOSoundPCMStream *stream;
+
+ if (!s->pcm->streams ||
+ !s->pcm->pcm_params ||
+ !s->pcm->pcm_params[stream_id]) {
+ return VIRTIO_SND_S_BAD_MSG;
+ }
+
+ params = virtio_snd_pcm_get_params(s, stream_id);
+ if (!params) {
+ return VIRTIO_SND_S_BAD_MSG;
+ }
+
+ virtio_snd_get_qemu_audsettings(&as, params);
+
+ stream = g_new0(VirtIOSoundPCMStream, 1);
+
+ stream->id = stream_id;
+ stream->pcm = s->pcm;
+ stream->direction = stream_id < s->snd_conf.streams / 2 +
+ (s->snd_conf.streams & 1) ? VIRTIO_SND_D_OUTPUT : VIRTIO_SND_D_INPUT;
+ stream->info.hdr.hda_fn_nid = VIRTIO_SOUND_HDA_FN_NID;
+ stream->features = 0;
+ stream->channels_min = 1;
+ stream->channels_max = as.nchannels;
+ stream->formats = supported_formats;
+ stream->rates = supported_rates;
+ stream->s = s;
+
+ stream->buffer_bytes = params->buffer_bytes;
+ stream->period_bytes = params->period_bytes;
+
+ stream->positions[0] = VIRTIO_SND_CHMAP_FL;
+ stream->positions[1] = VIRTIO_SND_CHMAP_FR;
+
+ stream->as = as;
+ stream->desired_as = stream->as;
+ qemu_mutex_init(&stream->queue_mutex);
+ QSIMPLEQ_INIT(&stream->queue);
+
+ s->pcm->streams[stream_id] = stream;
+
+ return VIRTIO_SND_S_OK;
+}
+
/*
* The actual processing done in virtio_snd_process_cmdq().
*
@@ -432,6 +558,13 @@ static void virtio_snd_common_realize(DeviceState *dev,
print_code(status));
return;
}
+ status = virtio_snd_pcm_prepare_impl(vsnd, i);
+ if (status != VIRTIO_SND_S_OK) {
+ error_setg(errp,
+ "Can't prepare streams, device responded with %s.",
+ print_code(status));
+ return;
+ }
}
}
--
2.39.2
^ permalink raw reply related [flat|nested] 22+ messages in thread
* [PATCH v4 06/12] virtio-sound: handle VIRTIO_SND_R_PCM_INFO request
2023-07-20 12:57 [PATCH v4 00/12] Add VIRTIO sound card Emmanouil Pitsidianakis
` (4 preceding siblings ...)
2023-07-20 12:57 ` [PATCH v4 05/12] virtio-sound: prepare PCM streams Emmanouil Pitsidianakis
@ 2023-07-20 12:57 ` Emmanouil Pitsidianakis
2023-07-25 14:29 ` Marc-André Lureau
2023-07-25 14:30 ` Marc-André Lureau
2023-07-20 12:57 ` [PATCH v4 07/12] virtio-sound: handle VIRTIO_SND_R_PCM_{START,STOP} Emmanouil Pitsidianakis
` (5 subsequent siblings)
11 siblings, 2 replies; 22+ messages in thread
From: Emmanouil Pitsidianakis @ 2023-07-20 12:57 UTC (permalink / raw)
To: qemu-devel
Cc: Emmanouil Pitsidianakis, Igor Skalkin, Anton Yakovlev,
Paolo Bonzini, Gerd Hoffmann, Michael S. Tsirkin,
Marcel Apfelbaum, Daniel P. Berrangé, Eduardo Habkost,
Marc-André Lureau, Volker Rümelin,
Kővágó, Zoltán, Alex Bennee,
Philippe Mathieu-Daudé
Respond to the VIRTIO_SND_R_PCM_INFO control request with the parameters
of each requested PCM stream.
Signed-off-by: Emmanouil Pitsidianakis <manos.pitsidianakis@linaro.org>
---
hw/virtio/trace-events | 1 +
hw/virtio/virtio-snd.c | 78 ++++++++++++++++++++++++++++++++++++++++++
2 files changed, 79 insertions(+)
diff --git a/hw/virtio/trace-events b/hw/virtio/trace-events
index 8a223e36e9..3e619f778b 100644
--- a/hw/virtio/trace-events
+++ b/hw/virtio/trace-events
@@ -164,6 +164,7 @@ virtio_snd_vm_state_stopped(void) "vm state stopped"
virtio_snd_realize(void *snd) "snd %p: realize"
virtio_snd_unrealize(void *snd) "snd %p: unrealize"
virtio_snd_handle_ctrl(void *vdev, void *vq) "snd %p: handle ctrl event for queue %p"
+virtio_snd_handle_pcm_info(uint32_t stream) "VIRTIO_SND_R_PCM_INFO called for stream %"PRIu32
virtio_snd_handle_code(uint32_t val, const char *code) "ctrl code msg val = %"PRIu32" == %s"
virtio_snd_handle_chmap_info(void) "VIRTIO_SND_CHMAP_INFO called"
virtio_snd_handle_event(void) "event queue callback called"
diff --git a/hw/virtio/virtio-snd.c b/hw/virtio/virtio-snd.c
index ca09c937c7..3f8b46f372 100644
--- a/hw/virtio/virtio-snd.c
+++ b/hw/virtio/virtio-snd.c
@@ -134,6 +134,19 @@ virtio_snd_set_config(VirtIODevice *vdev, const uint8_t *config)
memcpy(&s->snd_conf, sndconfig, sizeof(s->snd_conf));
}
+/*
+ * Get a specific stream from the virtio sound card device.
+ * Returns NULL if @stream_id is invalid or not allocated.
+ *
+ * @s: VirtIOSound device
+ * @stream_id: stream id
+ */
+static VirtIOSoundPCMStream *virtio_snd_pcm_get_stream(VirtIOSound *s,
+ uint32_t stream_id)
+{
+ return stream_id >= s->snd_conf.streams ? NULL : s->pcm->streams[stream_id];
+}
+
/*
* Get params for a specific stream.
*
@@ -147,6 +160,69 @@ static VirtIOSoundPCMParams *virtio_snd_pcm_get_params(VirtIOSound *s,
: s->pcm->pcm_params[stream_id];
}
+/*
+ * Handle the VIRTIO_SND_R_PCM_INFO request.
+ * The function writes the info structs to the request element.
+ *
+ * @s: VirtIOSound device
+ * @cmd: The request command queue element from VirtIOSound cmdq field
+ */
+static void virtio_snd_handle_pcm_info(VirtIOSound *s,
+ virtio_snd_ctrl_command *cmd)
+{
+ virtio_snd_query_info req;
+ VirtIOSoundPCMStream *stream = NULL;
+ g_autofree virtio_snd_pcm_info *pcm_info = NULL;
+ size_t sz = iov_to_buf(cmd->elem->out_sg,
+ cmd->elem->out_num,
+ 0,
+ &req,
+ sizeof(req));
+ if (sz != sizeof(virtio_snd_query_info)) {
+ cmd->resp.code = VIRTIO_SND_S_BAD_MSG;
+ return;
+ }
+
+ if (iov_size(cmd->elem->in_sg, cmd->elem->in_num) <
+ sizeof(virtio_snd_hdr) + req.size * req.count) {
+ error_report("pcm info: buffer too small, got: %lu, needed: %lu",
+ iov_size(cmd->elem->in_sg, cmd->elem->in_num),
+ sizeof(virtio_snd_pcm_info));
+ cmd->resp.code = VIRTIO_SND_S_BAD_MSG;
+ return;
+ }
+
+ pcm_info = g_new0(virtio_snd_pcm_info, req.count);
+ for (uint32_t i = req.start_id; i < req.start_id + req.count; i++) {
+ trace_virtio_snd_handle_pcm_info(i);
+ stream = virtio_snd_pcm_get_stream(s, i);
+
+ if (!stream) {
+ error_report("Invalid stream id: %"PRIu32, i);
+ cmd->resp.code = VIRTIO_SND_S_BAD_MSG;
+ return;
+ }
+
+ pcm_info[i - req.start_id].hdr.hda_fn_nid = stream->info.hdr.hda_fn_nid;
+ pcm_info[i - req.start_id].features = stream->features;
+ pcm_info[i - req.start_id].formats = stream->formats;
+ pcm_info[i - req.start_id].rates = stream->rates;
+ pcm_info[i - req.start_id].direction = stream->direction;
+ pcm_info[i - req.start_id].channels_min = stream->channels_min;
+ pcm_info[i - req.start_id].channels_max = stream->channels_max;
+
+ memset(&pcm_info[i].padding, 0, sizeof(pcm_info[i].padding));
+ }
+
+ cmd->resp.code = VIRTIO_SND_S_OK;
+
+ iov_from_buf(cmd->elem->in_sg,
+ cmd->elem->in_num,
+ sizeof(virtio_snd_hdr),
+ pcm_info,
+ sizeof(virtio_snd_pcm_info) * req.count);
+}
+
/*
* Set the given stream params.
* Called by both virtio_snd_handle_pcm_set_params and during device
@@ -358,6 +434,8 @@ process_cmd(VirtIOSound *s, virtio_snd_ctrl_command *cmd)
cmd->resp.code = VIRTIO_SND_S_NOT_SUPP;
break;
case VIRTIO_SND_R_PCM_INFO:
+ virtio_snd_handle_pcm_info(s, cmd);
+ break;
case VIRTIO_SND_R_PCM_SET_PARAMS:
case VIRTIO_SND_R_PCM_PREPARE:
case VIRTIO_SND_R_PCM_START:
--
2.39.2
^ permalink raw reply related [flat|nested] 22+ messages in thread
* [PATCH v4 07/12] virtio-sound: handle VIRTIO_SND_R_PCM_{START,STOP}
2023-07-20 12:57 [PATCH v4 00/12] Add VIRTIO sound card Emmanouil Pitsidianakis
` (5 preceding siblings ...)
2023-07-20 12:57 ` [PATCH v4 06/12] virtio-sound: handle VIRTIO_SND_R_PCM_INFO request Emmanouil Pitsidianakis
@ 2023-07-20 12:57 ` Emmanouil Pitsidianakis
2023-07-20 12:57 ` [PATCH v4 08/12] virtio-sound: handle VIRTIO_SND_PCM_SET_PARAMS Emmanouil Pitsidianakis
` (4 subsequent siblings)
11 siblings, 0 replies; 22+ messages in thread
From: Emmanouil Pitsidianakis @ 2023-07-20 12:57 UTC (permalink / raw)
To: qemu-devel
Cc: Emmanouil Pitsidianakis, Igor Skalkin, Anton Yakovlev,
Paolo Bonzini, Gerd Hoffmann, Michael S. Tsirkin,
Marcel Apfelbaum, Daniel P. Berrangé, Eduardo Habkost,
Marc-André Lureau, Volker Rümelin,
Kővágó, Zoltán, Alex Bennee,
Philippe Mathieu-Daudé
Handle the start and stop control messages for a stream_id. This request
does nothing at the moment except for replying to it. Audio playback
or capture will be started/stopped here in follow-up commits.
Signed-off-by: Emmanouil Pitsidianakis <manos.pitsidianakis@linaro.org>
---
hw/virtio/trace-events | 1 +
hw/virtio/virtio-snd.c | 42 ++++++++++++++++++++++++++++++++++++++++--
2 files changed, 41 insertions(+), 2 deletions(-)
diff --git a/hw/virtio/trace-events b/hw/virtio/trace-events
index 3e619f778b..8eae1bf881 100644
--- a/hw/virtio/trace-events
+++ b/hw/virtio/trace-events
@@ -165,6 +165,7 @@ virtio_snd_realize(void *snd) "snd %p: realize"
virtio_snd_unrealize(void *snd) "snd %p: unrealize"
virtio_snd_handle_ctrl(void *vdev, void *vq) "snd %p: handle ctrl event for queue %p"
virtio_snd_handle_pcm_info(uint32_t stream) "VIRTIO_SND_R_PCM_INFO called for stream %"PRIu32
+virtio_snd_handle_pcm_start_stop(const char *code, uint32_t stream) "%s called for stream %"PRIu32
virtio_snd_handle_code(uint32_t val, const char *code) "ctrl code msg val = %"PRIu32" == %s"
virtio_snd_handle_chmap_info(void) "VIRTIO_SND_CHMAP_INFO called"
virtio_snd_handle_event(void) "event queue callback called"
diff --git a/hw/virtio/virtio-snd.c b/hw/virtio/virtio-snd.c
index 3f8b46f372..0dc28d5bdc 100644
--- a/hw/virtio/virtio-snd.c
+++ b/hw/virtio/virtio-snd.c
@@ -402,6 +402,40 @@ static uint32_t virtio_snd_pcm_prepare_impl(VirtIOSound *s, uint32_t stream_id)
return VIRTIO_SND_S_OK;
}
+/*
+ * Handles VIRTIO_SND_R_PCM_START.
+ *
+ * @s: VirtIOSound device
+ * @cmd: The request command queue element from VirtIOSound cmdq field
+ * @start: whether to start or stop the device
+ */
+static void virtio_snd_handle_pcm_start_stop(VirtIOSound *s,
+ virtio_snd_ctrl_command *cmd,
+ bool start)
+{
+ VirtIOSoundPCMStream *stream;
+ virtio_snd_pcm_hdr req;
+ size_t sz = iov_to_buf(cmd->elem->out_sg,
+ cmd->elem->out_num,
+ 0,
+ &req,
+ sizeof(req));
+ if (sz != sizeof(virtio_snd_pcm_hdr)) {
+ cmd->resp.code = VIRTIO_SND_S_BAD_MSG;
+ return;
+ }
+
+ cmd->resp.code = VIRTIO_SND_S_OK;
+ trace_virtio_snd_handle_pcm_start_stop(start ? "VIRTIO_SND_R_PCM_START" :
+ "VIRTIO_SND_R_PCM_STOP", req.stream_id);
+
+ stream = virtio_snd_pcm_get_stream(s, req.stream_id);
+ if (!stream) {
+ error_report("Invalid stream id: %"PRIu32, req.stream_id);
+ cmd->resp.code = VIRTIO_SND_S_BAD_MSG;
+ }
+}
+
/*
* The actual processing done in virtio_snd_process_cmdq().
*
@@ -436,10 +470,14 @@ process_cmd(VirtIOSound *s, virtio_snd_ctrl_command *cmd)
case VIRTIO_SND_R_PCM_INFO:
virtio_snd_handle_pcm_info(s, cmd);
break;
- case VIRTIO_SND_R_PCM_SET_PARAMS:
- case VIRTIO_SND_R_PCM_PREPARE:
case VIRTIO_SND_R_PCM_START:
+ virtio_snd_handle_pcm_start_stop(s, cmd, true);
+ break;
case VIRTIO_SND_R_PCM_STOP:
+ virtio_snd_handle_pcm_start_stop(s, cmd, false);
+ break;
+ case VIRTIO_SND_R_PCM_SET_PARAMS:
+ case VIRTIO_SND_R_PCM_PREPARE:
case VIRTIO_SND_R_PCM_RELEASE:
cmd->resp.code = VIRTIO_SND_S_NOT_SUPP;
break;
--
2.39.2
^ permalink raw reply related [flat|nested] 22+ messages in thread
* [PATCH v4 08/12] virtio-sound: handle VIRTIO_SND_PCM_SET_PARAMS
2023-07-20 12:57 [PATCH v4 00/12] Add VIRTIO sound card Emmanouil Pitsidianakis
` (6 preceding siblings ...)
2023-07-20 12:57 ` [PATCH v4 07/12] virtio-sound: handle VIRTIO_SND_R_PCM_{START,STOP} Emmanouil Pitsidianakis
@ 2023-07-20 12:57 ` Emmanouil Pitsidianakis
2023-07-20 12:57 ` [PATCH v4 09/12] virtio-sound: handle VIRTIO_SND_R_PCM_PREPARE Emmanouil Pitsidianakis
` (3 subsequent siblings)
11 siblings, 0 replies; 22+ messages in thread
From: Emmanouil Pitsidianakis @ 2023-07-20 12:57 UTC (permalink / raw)
To: qemu-devel
Cc: Emmanouil Pitsidianakis, Igor Skalkin, Anton Yakovlev,
Paolo Bonzini, Gerd Hoffmann, Michael S. Tsirkin,
Marcel Apfelbaum, Daniel P. Berrangé, Eduardo Habkost,
Marc-André Lureau, Volker Rümelin,
Kővágó, Zoltán, Alex Bennee,
Philippe Mathieu-Daudé
Handle the set parameters control request. It reconfigures a stream
based on a guest's preference if the values are valid and supported.
Signed-off-by: Emmanouil Pitsidianakis <manos.pitsidianakis@linaro.org>
---
hw/virtio/trace-events | 1 +
hw/virtio/virtio-snd.c | 26 ++++++++++++++++++++++++++
2 files changed, 27 insertions(+)
diff --git a/hw/virtio/trace-events b/hw/virtio/trace-events
index 8eae1bf881..f70cde4f01 100644
--- a/hw/virtio/trace-events
+++ b/hw/virtio/trace-events
@@ -163,6 +163,7 @@ virtio_snd_vm_state_running(void) "vm state running"
virtio_snd_vm_state_stopped(void) "vm state stopped"
virtio_snd_realize(void *snd) "snd %p: realize"
virtio_snd_unrealize(void *snd) "snd %p: unrealize"
+virtio_snd_handle_pcm_set_params(uint32_t stream) "VIRTIO_SND_PCM_SET_PARAMS called for stream %"PRIu32
virtio_snd_handle_ctrl(void *vdev, void *vq) "snd %p: handle ctrl event for queue %p"
virtio_snd_handle_pcm_info(uint32_t stream) "VIRTIO_SND_R_PCM_INFO called for stream %"PRIu32
virtio_snd_handle_pcm_start_stop(const char *code, uint32_t stream) "%s called for stream %"PRIu32
diff --git a/hw/virtio/virtio-snd.c b/hw/virtio/virtio-snd.c
index 0dc28d5bdc..ea1f07a66a 100644
--- a/hw/virtio/virtio-snd.c
+++ b/hw/virtio/virtio-snd.c
@@ -276,6 +276,30 @@ uint32_t virtio_snd_pcm_set_params_impl(VirtIOSound *s,
return VIRTIO_SND_S_OK;
}
+/*
+ * Handles the VIRTIO_SND_R_PCM_SET_PARAMS request.
+ *
+ * @s: VirtIOSound device
+ * @cmd: The request command queue element from VirtIOSound cmdq field
+ */
+static void virtio_snd_handle_pcm_set_params(VirtIOSound *s,
+ virtio_snd_ctrl_command *cmd)
+{
+ virtio_snd_pcm_set_params req;
+ size_t sz = iov_to_buf(cmd->elem->out_sg,
+ cmd->elem->out_num,
+ 0,
+ &req,
+ sizeof(req));
+ if (sz != sizeof(virtio_snd_pcm_set_params)) {
+ cmd->resp.code = VIRTIO_SND_S_BAD_MSG;
+ return;
+ }
+
+ trace_virtio_snd_handle_pcm_set_params(req.hdr.stream_id);
+ cmd->resp.code = virtio_snd_pcm_set_params_impl(s, &req);
+}
+
/*
* Get a QEMU Audiosystem compatible format value from a VIRTIO_SND_PCM_FMT_*
*/
@@ -477,6 +501,8 @@ process_cmd(VirtIOSound *s, virtio_snd_ctrl_command *cmd)
virtio_snd_handle_pcm_start_stop(s, cmd, false);
break;
case VIRTIO_SND_R_PCM_SET_PARAMS:
+ virtio_snd_handle_pcm_set_params(s, cmd);
+ break;
case VIRTIO_SND_R_PCM_PREPARE:
case VIRTIO_SND_R_PCM_RELEASE:
cmd->resp.code = VIRTIO_SND_S_NOT_SUPP;
--
2.39.2
^ permalink raw reply related [flat|nested] 22+ messages in thread
* [PATCH v4 09/12] virtio-sound: handle VIRTIO_SND_R_PCM_PREPARE
2023-07-20 12:57 [PATCH v4 00/12] Add VIRTIO sound card Emmanouil Pitsidianakis
` (7 preceding siblings ...)
2023-07-20 12:57 ` [PATCH v4 08/12] virtio-sound: handle VIRTIO_SND_PCM_SET_PARAMS Emmanouil Pitsidianakis
@ 2023-07-20 12:57 ` Emmanouil Pitsidianakis
2023-07-20 12:57 ` [PATCH v4 10/12] virtio-sound: handle VIRTIO_SND_PCM_RELEASE Emmanouil Pitsidianakis
` (2 subsequent siblings)
11 siblings, 0 replies; 22+ messages in thread
From: Emmanouil Pitsidianakis @ 2023-07-20 12:57 UTC (permalink / raw)
To: qemu-devel
Cc: Emmanouil Pitsidianakis, Igor Skalkin, Anton Yakovlev,
Paolo Bonzini, Gerd Hoffmann, Michael S. Tsirkin,
Marcel Apfelbaum, Daniel P. Berrangé, Eduardo Habkost,
Marc-André Lureau, Volker Rümelin,
Kővágó, Zoltán, Alex Bennee,
Philippe Mathieu-Daudé
Handles the PCM prepare control request. It initializes a PCM stream
when the guests asks for it.
Signed-off-by: Emmanouil Pitsidianakis <manos.pitsidianakis@linaro.org>
---
hw/virtio/virtio-snd.c | 23 +++++++++++++++++++++++
1 file changed, 23 insertions(+)
diff --git a/hw/virtio/virtio-snd.c b/hw/virtio/virtio-snd.c
index ea1f07a66a..de82ed60ad 100644
--- a/hw/virtio/virtio-snd.c
+++ b/hw/virtio/virtio-snd.c
@@ -426,6 +426,27 @@ static uint32_t virtio_snd_pcm_prepare_impl(VirtIOSound *s, uint32_t stream_id)
return VIRTIO_SND_S_OK;
}
+/*
+ * Handles VIRTIO_SND_R_PCM_PREPARE.
+ *
+ * @s: VirtIOSound device
+ * @cmd: The request command queue element from VirtIOSound cmdq field
+ */
+static void virtio_snd_handle_pcm_prepare(VirtIOSound *s,
+ virtio_snd_ctrl_command *cmd)
+{
+ uint32_t stream_id;
+ size_t sz = iov_to_buf(cmd->elem->out_sg,
+ cmd->elem->out_num,
+ sizeof(virtio_snd_hdr),
+ &stream_id,
+ sizeof(stream_id));
+
+ cmd->resp.code = sz == sizeof(uint32_t)
+ ? virtio_snd_pcm_prepare_impl(s, stream_id)
+ : VIRTIO_SND_S_BAD_MSG;
+}
+
/*
* Handles VIRTIO_SND_R_PCM_START.
*
@@ -504,6 +525,8 @@ process_cmd(VirtIOSound *s, virtio_snd_ctrl_command *cmd)
virtio_snd_handle_pcm_set_params(s, cmd);
break;
case VIRTIO_SND_R_PCM_PREPARE:
+ virtio_snd_handle_pcm_prepare(s, cmd);
+ break;
case VIRTIO_SND_R_PCM_RELEASE:
cmd->resp.code = VIRTIO_SND_S_NOT_SUPP;
break;
--
2.39.2
^ permalink raw reply related [flat|nested] 22+ messages in thread
* [PATCH v4 10/12] virtio-sound: handle VIRTIO_SND_PCM_RELEASE
2023-07-20 12:57 [PATCH v4 00/12] Add VIRTIO sound card Emmanouil Pitsidianakis
` (8 preceding siblings ...)
2023-07-20 12:57 ` [PATCH v4 09/12] virtio-sound: handle VIRTIO_SND_R_PCM_PREPARE Emmanouil Pitsidianakis
@ 2023-07-20 12:57 ` Emmanouil Pitsidianakis
2023-07-20 12:57 ` [PATCH v4 11/12] virtio-sound: implement audio output (TX) Emmanouil Pitsidianakis
2023-07-20 12:57 ` [PATCH v4 12/12] virtio-sound: implement audio capture (RX) Emmanouil Pitsidianakis
11 siblings, 0 replies; 22+ messages in thread
From: Emmanouil Pitsidianakis @ 2023-07-20 12:57 UTC (permalink / raw)
To: qemu-devel
Cc: Emmanouil Pitsidianakis, Igor Skalkin, Anton Yakovlev,
Paolo Bonzini, Gerd Hoffmann, Michael S. Tsirkin,
Marcel Apfelbaum, Daniel P. Berrangé, Eduardo Habkost,
Marc-André Lureau, Volker Rümelin,
Kővágó, Zoltán, Alex Bennee,
Philippe Mathieu-Daudé
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.
Signed-off-by: Emmanouil Pitsidianakis <manos.pitsidianakis@linaro.org>
---
hw/virtio/trace-events | 1 +
hw/virtio/virtio-snd.c | 51 +++++++++++++++++++++++++++++++++++++++++-
2 files changed, 51 insertions(+), 1 deletion(-)
diff --git a/hw/virtio/trace-events b/hw/virtio/trace-events
index f70cde4f01..60ab62a80d 100644
--- a/hw/virtio/trace-events
+++ b/hw/virtio/trace-events
@@ -167,6 +167,7 @@ virtio_snd_handle_pcm_set_params(uint32_t stream) "VIRTIO_SND_PCM_SET_PARAMS cal
virtio_snd_handle_ctrl(void *vdev, void *vq) "snd %p: handle ctrl event for queue %p"
virtio_snd_handle_pcm_info(uint32_t stream) "VIRTIO_SND_R_PCM_INFO called for stream %"PRIu32
virtio_snd_handle_pcm_start_stop(const char *code, uint32_t stream) "%s called for stream %"PRIu32
+virtio_snd_handle_pcm_release(uint32_t stream) "VIRTIO_SND_PCM_RELEASE called for stream %"PRIu32
virtio_snd_handle_code(uint32_t val, const char *code) "ctrl code msg val = %"PRIu32" == %s"
virtio_snd_handle_chmap_info(void) "VIRTIO_SND_CHMAP_INFO called"
virtio_snd_handle_event(void) "event queue callback called"
diff --git a/hw/virtio/virtio-snd.c b/hw/virtio/virtio-snd.c
index de82ed60ad..e87783c38a 100644
--- a/hw/virtio/virtio-snd.c
+++ b/hw/virtio/virtio-snd.c
@@ -481,6 +481,55 @@ static void virtio_snd_handle_pcm_start_stop(VirtIOSound *s,
}
}
+/*
+ * Releases the buffer resources allocated to a stream. Seperated from the
+ * handler so that the code can be reused in the unrealize function. Returns
+ * the response status code. (VIRTIO_SND_S_*).
+ *
+ * @stream: VirtIOSoundPCMStream stream
+ * @stream_id: stream id
+ */
+static uint32_t virtio_snd_pcm_release_impl(VirtIOSoundPCMStream *stream,
+ uint32_t stream_id)
+{
+ return VIRTIO_SND_S_OK;
+}
+
+/*
+ * Handles VIRTIO_SND_R_PCM_RELEASE.
+ *
+ * @s: VirtIOSound device
+ * @cmd: The request command queue element from VirtIOSound cmdq field
+ */
+static void virtio_snd_handle_pcm_release(VirtIOSound *s,
+ virtio_snd_ctrl_command *cmd)
+{
+ uint32_t stream_id;
+ VirtIOSoundPCMStream *stream;
+ size_t sz = iov_to_buf(cmd->elem->out_sg,
+ cmd->elem->out_num,
+ sizeof(virtio_snd_hdr),
+ &stream_id,
+ sizeof(stream_id));
+ if (sz != sizeof(uint32_t)) {
+ cmd->resp.code = VIRTIO_SND_S_BAD_MSG;
+ return;
+ }
+
+ trace_virtio_snd_handle_pcm_release(stream_id);
+
+ stream = virtio_snd_pcm_get_stream(s, stream_id);
+ if (!stream) {
+ error_report("already released stream %"PRIu32, stream_id);
+ virtio_error(VIRTIO_DEVICE(s),
+ "already released stream %"PRIu32,
+ stream_id);
+ cmd->resp.code = VIRTIO_SND_S_BAD_MSG;
+ return;
+ }
+ cmd->resp.code = virtio_snd_pcm_release_impl(stream, stream_id);
+}
+
/*
* The actual processing done in virtio_snd_process_cmdq().
*
@@ -528,7 +577,7 @@ process_cmd(VirtIOSound *s, virtio_snd_ctrl_command *cmd)
virtio_snd_handle_pcm_prepare(s, cmd);
break;
case VIRTIO_SND_R_PCM_RELEASE:
- cmd->resp.code = VIRTIO_SND_S_NOT_SUPP;
+ virtio_snd_handle_pcm_release(s, cmd);
break;
case VIRTIO_SND_R_CHMAP_INFO:
qemu_log_mask(LOG_UNIMP,
--
2.39.2
^ permalink raw reply related [flat|nested] 22+ messages in thread
* [PATCH v4 11/12] virtio-sound: implement audio output (TX)
2023-07-20 12:57 [PATCH v4 00/12] Add VIRTIO sound card Emmanouil Pitsidianakis
` (9 preceding siblings ...)
2023-07-20 12:57 ` [PATCH v4 10/12] virtio-sound: handle VIRTIO_SND_PCM_RELEASE Emmanouil Pitsidianakis
@ 2023-07-20 12:57 ` Emmanouil Pitsidianakis
2023-07-20 12:57 ` [PATCH v4 12/12] virtio-sound: implement audio capture (RX) Emmanouil Pitsidianakis
11 siblings, 0 replies; 22+ messages in thread
From: Emmanouil Pitsidianakis @ 2023-07-20 12:57 UTC (permalink / raw)
To: qemu-devel
Cc: Emmanouil Pitsidianakis, Igor Skalkin, Anton Yakovlev,
Paolo Bonzini, Gerd Hoffmann, Michael S. Tsirkin,
Marcel Apfelbaum, Daniel P. Berrangé, Eduardo Habkost,
Marc-André Lureau, Volker Rümelin,
Kővágó, Zoltán, Alex Bennee,
Philippe Mathieu-Daudé
Handle output IO messages in the transmit (TX) virtqueue.
It allocates a VirtIOSoundPCMBlock for each IO message and copies the
data buffer to it. When the IO buffer is written to the host's sound
card, the guest will be notified that it has been consumed.
The lifetime of an IO message is:
1. Guest sends IO message to TX virtqueue.
2. QEMU adds it to the appropriate stream's IO buffer queue.
3. Sometime later, the host audio backend calls the output callback,
virtio_snd_pcm_out_cb(), which is defined with an AUD_open_out()
call. The callback gets an available number of bytes the backend can
receive. Then it writes data from the IO buffer queue to the backend.
If at any time a buffer is exhausted, it is returned to the guest as
completed.
4. If the guest releases the stream, its buffer queue is flushed by
attempting to write any leftover data to the audio backend and
releasing all IO messages back to the guest. This is how according to
the spec the guest knows the release was successful.
Signed-off-by: Emmanouil Pitsidianakis <manos.pitsidianakis@linaro.org>
---
hw/virtio/trace-events | 2 +
hw/virtio/virtio-snd.c | 254 ++++++++++++++++++++++++++++++++-
include/hw/virtio/virtio-snd.h | 11 ++
3 files changed, 260 insertions(+), 7 deletions(-)
diff --git a/hw/virtio/trace-events b/hw/virtio/trace-events
index 60ab62a80d..3b95e745c2 100644
--- a/hw/virtio/trace-events
+++ b/hw/virtio/trace-events
@@ -171,3 +171,5 @@ virtio_snd_handle_pcm_release(uint32_t stream) "VIRTIO_SND_PCM_RELEASE called fo
virtio_snd_handle_code(uint32_t val, const char *code) "ctrl code msg val = %"PRIu32" == %s"
virtio_snd_handle_chmap_info(void) "VIRTIO_SND_CHMAP_INFO called"
virtio_snd_handle_event(void) "event queue callback called"
+virtio_snd_pcm_stream_flush(uint32_t stream) "flushing stream %"PRIu32
+virtio_snd_handle_xfer(void) "tx/rx queue callback called"
diff --git a/hw/virtio/virtio-snd.c b/hw/virtio/virtio-snd.c
index e87783c38a..21983d9b8c 100644
--- a/hw/virtio/virtio-snd.c
+++ b/hw/virtio/virtio-snd.c
@@ -30,6 +30,15 @@
#define VIRTIO_SOUND_CHMAP_DEFAULT 0
#define VIRTIO_SOUND_HDA_FN_NID 0
+static void virtio_snd_pcm_out_cb(void *data, int available);
+static void virtio_snd_process_cmdq(VirtIOSound *s);
+static void virtio_snd_pcm_flush(VirtIOSoundPCMStream *stream);
+static uint32_t
+virtio_snd_pcm_read_write(VirtIOSoundPCMStream *stream,
+ VirtQueue *vq,
+ VirtQueueElement *element,
+ bool read);
+
static uint32_t supported_formats = BIT(VIRTIO_SND_PCM_FMT_S8)
| BIT(VIRTIO_SND_PCM_FMT_U8)
| BIT(VIRTIO_SND_PCM_FMT_S16)
@@ -416,6 +425,17 @@ static uint32_t virtio_snd_pcm_prepare_impl(VirtIOSound *s, uint32_t stream_id)
stream->positions[0] = VIRTIO_SND_CHMAP_FL;
stream->positions[1] = VIRTIO_SND_CHMAP_FR;
+ if (stream->direction == VIRTIO_SND_D_OUTPUT) {
+ stream->voice.out = AUD_open_out(&s->card,
+ stream->voice.out,
+ "virtio_snd_card",
+ stream,
+ virtio_snd_pcm_out_cb,
+ &as);
+ } else {
+ qemu_log_mask(LOG_UNIMP, "virtio_snd: input/capture is unimplemented.");
+ }
+
stream->as = as;
stream->desired_as = stream->as;
qemu_mutex_init(&stream->queue_mutex);
@@ -475,12 +495,35 @@ static void virtio_snd_handle_pcm_start_stop(VirtIOSound *s,
"VIRTIO_SND_R_PCM_STOP", req.stream_id);
stream = virtio_snd_pcm_get_stream(s, req.stream_id);
- if (!stream) {
+ if (stream) {
+ if (stream->direction == VIRTIO_SND_D_OUTPUT) {
+ AUD_set_active_out(stream->voice.out, start);
+ }
+ } else {
error_report("Invalid stream id: %"PRIu32, req.stream_id);
cmd->resp.code = VIRTIO_SND_S_BAD_MSG;
}
}
+/*
+ * Returns the number of bytes that have not been passed to AUD_write yet.
+ *
+ * @stream: VirtIOSoundPCMStream
+ */
+static size_t virtio_snd_pcm_get_pending_bytes(VirtIOSoundPCMStream *stream)
+{
+ VirtIOSoundPCMBlock *block;
+ VirtIOSoundPCMBlock *next;
+ size_t size = 0;
+
+ WITH_QEMU_LOCK_GUARD(&stream->queue_mutex) {
+ QSIMPLEQ_FOREACH_SAFE(block, &stream->queue, entry, next) {
+ size += block->size;
+ }
+ }
+ return size;
+}
+
/*
* Releases the buffer resources allocated to a stream. Seperated from the
* handler so that the code can be reused in the unrealize function. Returns
@@ -492,6 +535,21 @@ static void virtio_snd_handle_pcm_start_stop(VirtIOSound *s,
static uint32_t virtio_snd_pcm_release_impl(VirtIOSoundPCMStream *stream,
uint32_t stream_id)
{
+ if (virtio_snd_pcm_get_pending_bytes(stream)) {
+ /*
+ * virtio-v1.2-csd01, 5.14.6.6.5.1,
+ * Device Requirements: Stream Release
+ *
+ * - The device MUST complete all pending I/O messages for the
+ * specified stream ID.
+ * - The device MUST NOT complete the control request while there
+ * are pending I/O messages for the specified stream ID.
+ */
+ virtio_snd_process_cmdq(stream->s);
+ trace_virtio_snd_pcm_stream_flush(stream_id);
+ virtio_snd_pcm_flush(stream);
+ }
+
return VIRTIO_SND_S_OK;
}
@@ -676,6 +734,79 @@ static void virtio_snd_handle_event(VirtIODevice *vdev, VirtQueue *vq)
trace_virtio_snd_handle_event();
}
+/*
+ * The tx virtqueue handler. Makes the buffers available to their respective
+ * streams for consumption.
+ *
+ * @vdev: VirtIOSound device
+ * @vq: tx virtqueue
+ */
+static void virtio_snd_handle_tx(VirtIODevice *vdev, VirtQueue *vq)
+{
+ VirtIOSound *s = VIRTIO_SND(vdev);
+ VirtIOSoundPCMStream *stream = NULL;
+ VirtQueueElement *elem;
+ size_t sz;
+ virtio_snd_pcm_xfer hdr;
+ virtio_snd_pcm_status resp = { 0 };
+
+ trace_virtio_snd_handle_xfer();
+
+ for (;;) {
+ elem = virtqueue_pop(vq, sizeof(VirtQueueElement));
+ if (!elem) {
+ break;
+ }
+ /* get the message hdr object */
+ sz = iov_to_buf(elem->out_sg,
+ elem->out_num,
+ 0,
+ &hdr,
+ sizeof(hdr));
+ if (sz != sizeof(hdr)
+ || hdr.stream_id >= s->snd_conf.streams
+ || !s->pcm->streams[hdr.stream_id]) {
+ goto tx_err;
+ }
+
+ stream = s->pcm->streams[hdr.stream_id];
+ if (stream->direction == VIRTIO_SND_D_INPUT) {
+ goto tx_err;
+ }
+
+ WITH_QEMU_LOCK_GUARD(&stream->queue_mutex) {
+ virtio_snd_pcm_read_write(stream,
+ vq,
+ elem,
+ hdr.stream_id == VIRTIO_SND_D_INPUT);
+
+ resp.status = VIRTIO_SND_S_OK;
+ iov_from_buf(elem->in_sg,
+ elem->in_num,
+ 0,
+ &resp,
+ sizeof(resp));
+ }
+ continue;
+
+tx_err:
+ WITH_QEMU_LOCK_GUARD(&stream->queue_mutex) {
+ resp.status = VIRTIO_SND_S_BAD_MSG;
+ iov_from_buf(elem->in_sg,
+ elem->in_num,
+ 0,
+ &resp,
+ sizeof(resp));
+ }
+ }
+
+ /*
+ * Notify vq about virtio_snd_pcm_status responses.
+ * Buffer responses must be notified separately later.
+ */
+ virtio_notify(VIRTIO_DEVICE(s), vq);
+}
+
/*
* Stub buffer virtqueue handler.
*
@@ -806,7 +937,7 @@ 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,
&err);
if (err != NULL) {
@@ -814,6 +945,73 @@ static void virtio_snd_realize(DeviceState *dev, Error **errp)
}
}
+/*
+ * AUD_* output callback.
+ *
+ * @data: VirtIOSoundPCMStream stream
+ * @available: number of bytes that can be written with AUD_write()
+ */
+static void virtio_snd_pcm_out_cb(void *data, int available)
+{
+ VirtIOSoundPCMStream *stream = data;
+ VirtIOSoundPCMBlock *block;
+ VirtIOSoundPCMBlock *next;
+ size_t size;
+
+ WITH_QEMU_LOCK_GUARD(&stream->queue_mutex) {
+ QSIMPLEQ_FOREACH_SAFE(block, &stream->queue, entry, next) {
+ for (;;) {
+ size = MIN(block->size, available);
+ size = AUD_write(stream->voice.out,
+ block->data + block->offset,
+ size);
+ block->size -= size;
+ block->offset += size;
+ if (!block->size) {
+ 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);
+ available -= size;
+ break;
+ }
+
+ available -= size;
+ if (!available) {
+ break;
+ }
+ }
+ if (!available) {
+ break;
+ }
+ }
+ }
+}
+
+/*
+ * Flush all buffer data from this stream's queue into the driver's virtual
+ * queue.
+ *
+ * @stream: VirtIOSoundPCMStream *stream
+ */
+static void virtio_snd_pcm_flush(VirtIOSoundPCMStream *stream)
+{
+ VirtIOSoundPCMBlock *block;
+ VirtIOSoundPCMBlock *next;
+
+ WITH_QEMU_LOCK_GUARD(&stream->queue_mutex) {
+ QSIMPLEQ_FOREACH_SAFE(block, &stream->queue, entry, next) {
+ AUD_write(stream->voice.out, block->data, 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);
+ }
+ }
+}
+
/*
* Close the sound card.
*
@@ -822,6 +1020,10 @@ static void virtio_snd_realize(DeviceState *dev, Error **errp)
static void virtio_snd_pcm_close(VirtIOSoundPCMStream *stream)
{
virtio_snd_process_cmdq(stream->s);
+ if (stream->direction == VIRTIO_SND_D_OUTPUT) {
+ AUD_close_out(&stream->pcm->snd->card, stream->voice.out);
+ stream->voice.out = NULL;
+ }
}
static void virtio_snd_unrealize(DeviceState *dev)
@@ -835,17 +1037,55 @@ static void virtio_snd_unrealize(DeviceState *dev)
trace_virtio_snd_unrealize(vsnd);
- for (uint32_t i = 0; i < vsnd->snd_conf.streams; i++) {
- stream = vsnd->pcm->streams[i];
- virtio_snd_pcm_close(stream);
- g_free(stream);
+ if (vsnd->pcm) {
+ if (vsnd->pcm->streams) {
+ for (uint32_t i = 0; i < vsnd->snd_conf.streams; i++) {
+ stream = vsnd->pcm->streams[i];
+ if (stream) {
+ virtio_snd_pcm_close(stream);
+ g_free(stream);
+ }
+ }
+ g_free(vsnd->pcm->streams);
+ g_free(vsnd->pcm->pcm_params);
+ g_free(vsnd->pcm->jacks);
+ }
+
+ g_free(vsnd->pcm);
}
+
+ vsnd->pcm = NULL;
AUD_remove_card(&vsnd->card);
- g_free(vsnd->pcm);
virtio_cleanup(vdev);
}
+static uint32_t
+virtio_snd_pcm_read_write(VirtIOSoundPCMStream *stream,
+ VirtQueue *vq,
+ VirtQueueElement *element,
+ bool read)
+{
+ VirtIOSoundPCMBlock *fragment;
+ size_t size = iov_size(element->out_sg, element->out_num) -
+ sizeof(virtio_snd_pcm_xfer);
+
+ fragment = g_malloc0(sizeof(VirtIOSoundPCMBlock) + size);
+ fragment->elem = element;
+ fragment->vq = vq;
+ fragment->size = size;
+ fragment->offset = 0;
+
+ iov_to_buf(element->out_sg, element->out_num,
+ sizeof(virtio_snd_pcm_xfer),
+ fragment->data,
+ size);
+
+ QSIMPLEQ_INSERT_TAIL(&stream->queue, fragment, entry);
+
+ return fragment->size;
+}
+
static void virtio_snd_reset(VirtIODevice *vdev)
{
VirtIOSound *s = VIRTIO_SND(vdev);
diff --git a/include/hw/virtio/virtio-snd.h b/include/hw/virtio/virtio-snd.h
index 1a9835841d..156e1f5edd 100644
--- a/include/hw/virtio/virtio-snd.h
+++ b/include/hw/virtio/virtio-snd.h
@@ -81,6 +81,8 @@ typedef struct VirtIOSoundPCMParams VirtIOSoundPCMParams;
typedef struct VirtIOSoundPCM VirtIOSoundPCM;
+typedef struct VirtIOSoundPCMBlock VirtIOSoundPCMBlock;
+
/* Stream params */
struct VirtIOSoundPCMParams {
uint32_t features;
@@ -91,6 +93,15 @@ struct VirtIOSoundPCMParams {
uint8_t rate;
};
+struct VirtIOSoundPCMBlock {
+ QSIMPLEQ_ENTRY(VirtIOSoundPCMBlock) entry;
+ VirtQueueElement *elem;
+ VirtQueue *vq;
+ size_t size;
+ uint64_t offset;
+ uint8_t data[];
+};
+
struct VirtIOSoundPCM {
VirtIOSound *snd;
VirtIOSoundPCMParams **pcm_params;
--
2.39.2
^ permalink raw reply related [flat|nested] 22+ messages in thread
* [PATCH v4 12/12] virtio-sound: implement audio capture (RX)
2023-07-20 12:57 [PATCH v4 00/12] Add VIRTIO sound card Emmanouil Pitsidianakis
` (10 preceding siblings ...)
2023-07-20 12:57 ` [PATCH v4 11/12] virtio-sound: implement audio output (TX) Emmanouil Pitsidianakis
@ 2023-07-20 12:57 ` Emmanouil Pitsidianakis
11 siblings, 0 replies; 22+ messages in thread
From: Emmanouil Pitsidianakis @ 2023-07-20 12:57 UTC (permalink / raw)
To: qemu-devel
Cc: Emmanouil Pitsidianakis, Igor Skalkin, Anton Yakovlev,
Paolo Bonzini, Gerd Hoffmann, Michael S. Tsirkin,
Marcel Apfelbaum, Daniel P. Berrangé, Eduardo Habkost,
Marc-André Lureau, Volker Rümelin,
Kővágó, Zoltán, Alex Bennee,
Philippe Mathieu-Daudé
To perform audio capture we duplicate the TX logic of the previous
commit with the following difference: we receive data from the QEMU
audio backend and write it in the virt queue IO buffers the guest sends
to QEMU. When they are full (i.e. they have `period_bytes` amount of
data) or when recording stops in QEMU's audio backend, the buffer is
returned to the guest by notifying it.
Signed-off-by: Emmanouil Pitsidianakis <manos.pitsidianakis@linaro.org>
---
hw/virtio/trace-events | 3 +-
hw/virtio/virtio-snd.c | 230 +++++++++++++++++++++++++++++++++++------
2 files changed, 200 insertions(+), 33 deletions(-)
diff --git a/hw/virtio/trace-events b/hw/virtio/trace-events
index 3b95e745c2..a5829b112c 100644
--- a/hw/virtio/trace-events
+++ b/hw/virtio/trace-events
@@ -172,4 +172,5 @@ virtio_snd_handle_code(uint32_t val, const char *code) "ctrl code msg val = %"PR
virtio_snd_handle_chmap_info(void) "VIRTIO_SND_CHMAP_INFO called"
virtio_snd_handle_event(void) "event queue callback called"
virtio_snd_pcm_stream_flush(uint32_t stream) "flushing stream %"PRIu32
-virtio_snd_handle_xfer(void) "tx/rx queue callback called"
+virtio_snd_handle_tx_xfer(void) "tx queue callback called"
+virtio_snd_handle_rx_xfer(void) "tx queue callback called"
diff --git a/hw/virtio/virtio-snd.c b/hw/virtio/virtio-snd.c
index 21983d9b8c..0643246434 100644
--- a/hw/virtio/virtio-snd.c
+++ b/hw/virtio/virtio-snd.c
@@ -26,18 +26,21 @@
#define VIRTIO_SOUND_VM_VERSION 1
#define VIRTIO_SOUND_JACK_DEFAULT 0
-#define VIRTIO_SOUND_STREAM_DEFAULT 1
+#define VIRTIO_SOUND_STREAM_DEFAULT 2
#define VIRTIO_SOUND_CHMAP_DEFAULT 0
#define VIRTIO_SOUND_HDA_FN_NID 0
static void virtio_snd_pcm_out_cb(void *data, int available);
static void virtio_snd_process_cmdq(VirtIOSound *s);
-static void virtio_snd_pcm_flush(VirtIOSoundPCMStream *stream);
-static uint32_t
-virtio_snd_pcm_read_write(VirtIOSoundPCMStream *stream,
- VirtQueue *vq,
- VirtQueueElement *element,
- bool read);
+static void virtio_snd_pcm_out_flush(VirtIOSoundPCMStream *stream);
+static void virtio_snd_pcm_in_flush(VirtIOSoundPCMStream *stream);
+static void virtio_snd_pcm_in_cb(void *data, int available);
+static uint32_t virtio_snd_pcm_write(VirtIOSoundPCMStream *stream,
+ VirtQueue *vq,
+ VirtQueueElement *element);
+static uint32_t virtio_snd_pcm_read(VirtIOSoundPCMStream *stream,
+ VirtQueue *vq,
+ VirtQueueElement *element);
static uint32_t supported_formats = BIT(VIRTIO_SND_PCM_FMT_S8)
| BIT(VIRTIO_SND_PCM_FMT_U8)
@@ -433,7 +436,12 @@ static uint32_t virtio_snd_pcm_prepare_impl(VirtIOSound *s, uint32_t stream_id)
virtio_snd_pcm_out_cb,
&as);
} else {
- qemu_log_mask(LOG_UNIMP, "virtio_snd: input/capture is unimplemented.");
+ stream->voice.in = AUD_open_in(&s->card,
+ stream->voice.in,
+ "virtio_snd_card",
+ stream,
+ virtio_snd_pcm_in_cb,
+ &as);
}
stream->as = as;
@@ -498,6 +506,8 @@ static void virtio_snd_handle_pcm_start_stop(VirtIOSound *s,
if (stream) {
if (stream->direction == VIRTIO_SND_D_OUTPUT) {
AUD_set_active_out(stream->voice.out, start);
+ } else {
+ AUD_set_active_in(stream->voice.in, start);
}
} else {
error_report("Invalid stream id: %"PRIu32, req.stream_id);
@@ -547,7 +557,11 @@ static uint32_t virtio_snd_pcm_release_impl(VirtIOSoundPCMStream *stream,
*/
virtio_snd_process_cmdq(stream->s);
trace_virtio_snd_pcm_stream_flush(stream_id);
- virtio_snd_pcm_flush(stream);
+ if (stream->direction == VIRTIO_SND_D_OUTPUT) {
+ virtio_snd_pcm_out_flush(stream);
+ } else {
+ virtio_snd_pcm_in_flush(stream);
+ }
}
return VIRTIO_SND_S_OK;
@@ -741,7 +755,7 @@ static void virtio_snd_handle_event(VirtIODevice *vdev, VirtQueue *vq)
* @vdev: VirtIOSound device
* @vq: tx virtqueue
*/
-static void virtio_snd_handle_tx(VirtIODevice *vdev, VirtQueue *vq)
+static void virtio_snd_handle_tx_xfer(VirtIODevice *vdev, VirtQueue *vq)
{
VirtIOSound *s = VIRTIO_SND(vdev);
VirtIOSoundPCMStream *stream = NULL;
@@ -750,7 +764,7 @@ static void virtio_snd_handle_tx(VirtIODevice *vdev, VirtQueue *vq)
virtio_snd_pcm_xfer hdr;
virtio_snd_pcm_status resp = { 0 };
- trace_virtio_snd_handle_xfer();
+ trace_virtio_snd_handle_tx_xfer();
for (;;) {
elem = virtqueue_pop(vq, sizeof(VirtQueueElement));
@@ -774,11 +788,11 @@ static void virtio_snd_handle_tx(VirtIODevice *vdev, VirtQueue *vq)
goto tx_err;
}
+ assert(hdr.stream_id != VIRTIO_SND_D_INPUT);
WITH_QEMU_LOCK_GUARD(&stream->queue_mutex) {
- virtio_snd_pcm_read_write(stream,
+ virtio_snd_pcm_write(stream,
vq,
- elem,
- hdr.stream_id == VIRTIO_SND_D_INPUT);
+ elem);
resp.status = VIRTIO_SND_S_OK;
iov_from_buf(elem->in_sg,
@@ -808,12 +822,54 @@ tx_err:
}
/*
- * Stub buffer virtqueue handler.
+ * The rx virtqueue handler. Makes the buffers available to their respective
+ * streams for consumption.
*
* @vdev: VirtIOSound device
- * @vq: virtqueue
+ * @vq: tx virtqueue
*/
-static void virtio_snd_handle_xfer(VirtIODevice *vdev, VirtQueue *vq) {}
+static void virtio_snd_handle_rx_xfer(VirtIODevice *vdev, VirtQueue *vq)
+{
+ VirtIOSound *s = VIRTIO_SND(vdev);
+ VirtIOSoundPCMStream *stream = NULL;
+ VirtQueueElement *elem;
+ size_t sz;
+ virtio_snd_pcm_xfer hdr;
+
+ trace_virtio_snd_handle_rx_xfer();
+
+ for (;;) {
+ elem = virtqueue_pop(vq, sizeof(VirtQueueElement));
+ if (!elem) {
+ break;
+ }
+ /* get the message hdr object */
+ sz = iov_to_buf(elem->out_sg,
+ elem->out_num,
+ 0,
+ &hdr,
+ sizeof(hdr));
+ if (sz != sizeof(hdr)
+ || hdr.stream_id >= s->snd_conf.streams
+ || !s->pcm->streams[hdr.stream_id]) {
+ continue;
+ }
+
+ stream = s->pcm->streams[hdr.stream_id];
+ if (stream->direction == VIRTIO_SND_D_OUTPUT) {
+ continue;
+ }
+ WITH_QEMU_LOCK_GUARD(&stream->queue_mutex) {
+ virtio_snd_pcm_read(stream, vq, elem);
+ }
+ }
+
+ /*
+ * Notify vq about virtio_snd_pcm_status responses.
+ * Buffer responses must be notified separately later.
+ */
+ virtio_notify(VIRTIO_DEVICE(s), vq);
+}
static uint64_t get_features(VirtIODevice *vdev, uint64_t features,
Error **errp)
@@ -937,8 +993,8 @@ 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,
&err);
if (err != NULL) {
error_propagate(errp, err);
@@ -992,26 +1048,119 @@ static void virtio_snd_pcm_out_cb(void *data, int available)
}
/*
- * Flush all buffer data from this stream's queue into the driver's virtual
- * queue.
+ * AUD_* input callback.
*
- * @stream: VirtIOSoundPCMStream *stream
+ * @data: VirtIOSoundPCMStream stream
+ * @available: number of bytes that can be read with AUD_read()
*/
-static void virtio_snd_pcm_flush(VirtIOSoundPCMStream *stream)
+static void virtio_snd_pcm_in_cb(void *data, int available)
{
+ VirtIOSoundPCMStream *stream = data;
VirtIOSoundPCMBlock *block;
- VirtIOSoundPCMBlock *next;
+ uint32_t sz;
+ virtio_snd_pcm_status resp = { 0 };
+ size_t size;
WITH_QEMU_LOCK_GUARD(&stream->queue_mutex) {
- QSIMPLEQ_FOREACH_SAFE(block, &stream->queue, entry, next) {
- AUD_write(stream->voice.out, block->data, 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);
+ while (!QSIMPLEQ_EMPTY(&stream->queue)) {
+ block = QSIMPLEQ_FIRST(&stream->queue);
+
+ for (;;) {
+ size = AUD_read(stream->voice.in,
+ block->data + block->offset,
+ MIN(stream->period_bytes - block->offset, available));
+ block->offset += size;
+ block->size += size;
+ if (size == 0 || block->size >= stream->period_bytes) {
+ resp.status = VIRTIO_SND_S_OK;
+ sz = iov_from_buf(block->elem->in_sg,
+ block->elem->in_num,
+ 0,
+ &resp,
+ sizeof(resp));
+
+ /* Copy data -if any- to guest */
+ if (block->size) {
+ iov_from_buf(block->elem->in_sg,
+ block->elem->in_num,
+ sz,
+ &block->data,
+ MIN(stream->period_bytes, block->size));
+ }
+ 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);
+ available -= size;
+ break;
+ }
+
+ available -= size;
+ if (!available) {
+ break;
+ }
+ }
+ if (!available) {
+ break;
+ }
}
}
}
+#define virtio_snd_pcm_flush(AUD_CB) \
+ VirtIOSoundPCMBlock *block; \
+ VirtIOSoundPCMBlock *next; \
+ WITH_QEMU_LOCK_GUARD(&stream->queue_mutex) { \
+ QSIMPLEQ_FOREACH_SAFE(block, &stream->queue, entry, next) { \
+ do { \
+ AUD_CB; \
+ } while (0) \
+ ; \
+ virtqueue_push(block->vq, block->elem, sizeof(block->elem));\
+ virtio_notify(VIRTIO_DEVICE(stream->s), block->vq); \
+ QSIMPLEQ_REMOVE(&stream->queue, \
+ block, \
+ VirtIOSoundPCMBlock, \
+ entry); \
+ } \
+ } \
+
+
+/*
+ * Flush all buffer data from this output stream's queue into the driver's
+ * virtual queue.
+ *
+ * @stream: VirtIOSoundPCMStream *stream
+ */
+static void virtio_snd_pcm_out_flush(VirtIOSoundPCMStream *stream)
+{
+ virtio_snd_pcm_flush(
+ AUD_write(stream->voice.out,
+ block->data,
+ block->size);
+ );
+}
+
+/*
+ * Flush all buffer data from this input stream's queue into the driver's
+ * virtual queue.
+ *
+ * @stream: VirtIOSoundPCMStream *stream
+ */
+static void virtio_snd_pcm_in_flush(VirtIOSoundPCMStream *stream)
+{
+ virtio_snd_pcm_flush(
+ iov_from_buf(block->elem->in_sg,
+ block->elem->in_num,
+ sizeof(virtio_snd_pcm_info),
+ block->data,
+ block->offset);
+ );
+}
+
/*
* Close the sound card.
*
@@ -1061,10 +1210,9 @@ static void virtio_snd_unrealize(DeviceState *dev)
static uint32_t
-virtio_snd_pcm_read_write(VirtIOSoundPCMStream *stream,
+virtio_snd_pcm_write(VirtIOSoundPCMStream *stream,
VirtQueue *vq,
- VirtQueueElement *element,
- bool read)
+ VirtQueueElement *element)
{
VirtIOSoundPCMBlock *fragment;
size_t size = iov_size(element->out_sg, element->out_num) -
@@ -1086,6 +1234,24 @@ virtio_snd_pcm_read_write(VirtIOSoundPCMStream *stream,
return fragment->size;
}
+static uint32_t
+virtio_snd_pcm_read(VirtIOSoundPCMStream *stream,
+ VirtQueue *vq,
+ VirtQueueElement *element)
+{
+ VirtIOSoundPCMBlock *fragment;
+
+ fragment = g_malloc0(sizeof(VirtIOSoundPCMBlock) + stream->period_bytes);
+ fragment->elem = element;
+ fragment->vq = vq;
+ fragment->size = 0;
+ fragment->offset = 0;
+
+ QSIMPLEQ_INSERT_TAIL(&stream->queue, fragment, entry);
+
+ return fragment->size;
+}
+
static void virtio_snd_reset(VirtIODevice *vdev)
{
VirtIOSound *s = VIRTIO_SND(vdev);
--
2.39.2
^ permalink raw reply related [flat|nested] 22+ messages in thread
* Re: [PATCH v4 05/12] virtio-sound: prepare PCM streams
2023-07-20 12:57 ` [PATCH v4 05/12] virtio-sound: prepare PCM streams Emmanouil Pitsidianakis
@ 2023-07-25 13:38 ` Marc-André Lureau
0 siblings, 0 replies; 22+ messages in thread
From: Marc-André Lureau @ 2023-07-25 13:38 UTC (permalink / raw)
To: Emmanouil Pitsidianakis
Cc: qemu-devel, Igor Skalkin, Anton Yakovlev, Paolo Bonzini,
Gerd Hoffmann, Michael S. Tsirkin, Marcel Apfelbaum,
Daniel P. Berrangé, Eduardo Habkost, Volker Rümelin,
Kővágó, Zoltán, Alex Bennee,
Philippe Mathieu-Daudé
[-- Attachment #1: Type: text/plain, Size: 4986 bytes --]
Hi
On Thu, Jul 20, 2023 at 4:59 PM Emmanouil Pitsidianakis <
manos.pitsidianakis@linaro.org> wrote:
> After setting PCM parameters, instantiate ("prepare") each stream in
> virtio_snd_pcm_prepare_impl().
>
> Signed-off-by: Emmanouil Pitsidianakis <manos.pitsidianakis@linaro.org>
> ---
> hw/virtio/virtio-snd.c | 133 +++++++++++++++++++++++++++++++++++++++++
> 1 file changed, 133 insertions(+)
>
> diff --git a/hw/virtio/virtio-snd.c b/hw/virtio/virtio-snd.c
> index 62d9bf557c..ca09c937c7 100644
> --- a/hw/virtio/virtio-snd.c
> +++ b/hw/virtio/virtio-snd.c
> @@ -200,6 +200,132 @@ uint32_t virtio_snd_pcm_set_params_impl(VirtIOSound
> *s,
> return VIRTIO_SND_S_OK;
> }
>
> +/*
> + * Get a QEMU Audiosystem compatible format value from a
> VIRTIO_SND_PCM_FMT_*
> + */
> +static AudioFormat virtio_snd_get_qemu_format(uint32_t format)
> +{
> + #define CASE(FMT) \
> + case VIRTIO_SND_PCM_FMT_##FMT: \
> + return AUDIO_FORMAT_##FMT;
> +
> + switch (format) {
> + CASE(U8)
> + CASE(S8)
> + CASE(U16)
> + CASE(S16)
> + CASE(U32)
> + CASE(S32)
> + case VIRTIO_SND_PCM_FMT_FLOAT:
> + return AUDIO_FORMAT_F32;
> + default:
> + g_assert_not_reached();
> + }
> +
> + #undef CASE
> +}
> +
> +/*
> + * Get a QEMU Audiosystem compatible frequency value from a
> + * VIRTIO_SND_PCM_RATE_*
> + */
> +static uint32_t virtio_snd_get_qemu_freq(uint32_t rate)
> +{
> + #define CASE(RATE) \
> + case VIRTIO_SND_PCM_RATE_##RATE: \
> + return RATE;
> +
> + switch (rate) {
> + CASE(5512)
> + CASE(8000)
> + CASE(11025)
> + CASE(16000)
> + CASE(22050)
> + CASE(32000)
> + CASE(44100)
> + CASE(48000)
> + CASE(64000)
> + CASE(88200)
> + CASE(96000)
> + CASE(176400)
> + CASE(192000)
> + CASE(384000)
> + default:
> + g_assert_not_reached();
> + }
> +
> + #undef CASE
> +}
> +
> +/*
> + * Get QEMU Audiosystem compatible audsettings from virtio based pcm
> stream
> + * params.
> + */
> +static void virtio_snd_get_qemu_audsettings(audsettings *as,
> + VirtIOSoundPCMParams *params)
> +{
> + as->nchannels = MIN(AUDIO_MAX_CHANNELS, params->channels);
> + as->fmt = virtio_snd_get_qemu_format(params->format);
> + as->freq = virtio_snd_get_qemu_freq(params->rate);
> + as->endianness = AUDIO_HOST_ENDIANNESS;
> +}
> +
> +/*
> + * Prepares a VirtIOSound card stream.
> + * Returns the response status code. (VIRTIO_SND_S_*).
> + *
> + * @s: VirtIOSound device
> + * @stream_id: stream id
> + */
> +static uint32_t virtio_snd_pcm_prepare_impl(VirtIOSound *s, uint32_t
> stream_id)
> +{
> + audsettings as;
> + VirtIOSoundPCMParams *params;
> + VirtIOSoundPCMStream *stream;
> +
> + if (!s->pcm->streams ||
> + !s->pcm->pcm_params ||
> + !s->pcm->pcm_params[stream_id]) {
> + return VIRTIO_SND_S_BAD_MSG;
> + }
> +
> + params = virtio_snd_pcm_get_params(s, stream_id);
> + if (!params) {
> + return VIRTIO_SND_S_BAD_MSG;
> + }
> +
> + virtio_snd_get_qemu_audsettings(&as, params);
> +
> + stream = g_new0(VirtIOSoundPCMStream, 1);
> +
> + stream->id = stream_id;
> + stream->pcm = s->pcm;
> + stream->direction = stream_id < s->snd_conf.streams / 2 +
> + (s->snd_conf.streams & 1) ? VIRTIO_SND_D_OUTPUT :
> VIRTIO_SND_D_INPUT;
> + stream->info.hdr.hda_fn_nid = VIRTIO_SOUND_HDA_FN_NID;
> + stream->features = 0;
> + stream->channels_min = 1;
> + stream->channels_max = as.nchannels;
> + stream->formats = supported_formats;
> + stream->rates = supported_rates;
> + stream->s = s;
> +
> + stream->buffer_bytes = params->buffer_bytes;
> + stream->period_bytes = params->period_bytes;
> +
> + stream->positions[0] = VIRTIO_SND_CHMAP_FL;
> + stream->positions[1] = VIRTIO_SND_CHMAP_FR;
> +
> + stream->as = as;
> + stream->desired_as = stream->as;
> + qemu_mutex_init(&stream->queue_mutex);
> + QSIMPLEQ_INIT(&stream->queue);
> +
> + s->pcm->streams[stream_id] = stream;
>
Shouldn't it close & free the existing stream? Or return an error?
> +
> + return VIRTIO_SND_S_OK;
> +}
> +
> /*
> * The actual processing done in virtio_snd_process_cmdq().
> *
> @@ -432,6 +558,13 @@ static void virtio_snd_common_realize(DeviceState
> *dev,
> print_code(status));
> return;
> }
> + status = virtio_snd_pcm_prepare_impl(vsnd, i);
> + if (status != VIRTIO_SND_S_OK) {
> + error_setg(errp,
> + "Can't prepare streams, device responded with %s.",
> + print_code(status));
> + return;
> + }
> }
> }
>
> --
> 2.39.2
>
>
>
--
Marc-André Lureau
[-- Attachment #2: Type: text/html, Size: 6424 bytes --]
^ permalink raw reply [flat|nested] 22+ messages in thread
* Re: [PATCH v4 01/12] Add virtio-sound device stub
2023-07-20 12:57 ` [PATCH v4 01/12] Add virtio-sound device stub Emmanouil Pitsidianakis
@ 2023-07-25 14:22 ` Marc-André Lureau
2023-07-25 14:31 ` Marc-André Lureau
1 sibling, 0 replies; 22+ messages in thread
From: Marc-André Lureau @ 2023-07-25 14:22 UTC (permalink / raw)
To: Emmanouil Pitsidianakis
Cc: qemu-devel, Igor Skalkin, Anton Yakovlev, Paolo Bonzini,
Gerd Hoffmann, Michael S. Tsirkin, Marcel Apfelbaum,
Daniel P. Berrangé, Eduardo Habkost, Volker Rümelin,
Kővágó, Zoltán, Alex Bennee,
Philippe Mathieu-Daudé
[-- Attachment #1: Type: text/plain, Size: 14591 bytes --]
On Thu, Jul 20, 2023 at 4:58 PM Emmanouil Pitsidianakis <
manos.pitsidianakis@linaro.org> wrote:
> Add a new VIRTIO device for the virtio sound device id. Functionality
> will be added in the following commits.
>
> Signed-off-by: Emmanouil Pitsidianakis <manos.pitsidianakis@linaro.org>
> ---
> MAINTAINERS | 6 +
> hw/virtio/Kconfig | 5 +
> hw/virtio/meson.build | 1 +
> hw/virtio/trace-events | 9 ++
> hw/virtio/virtio-snd.c | 230 +++++++++++++++++++++++++++++++++
> include/hw/virtio/virtio-snd.h | 79 +++++++++++
> 6 files changed, 330 insertions(+)
> create mode 100644 hw/virtio/virtio-snd.c
> create mode 100644 include/hw/virtio/virtio-snd.h
>
> diff --git a/MAINTAINERS b/MAINTAINERS
> index 12e59b6b27..2bed60f9c1 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -2245,6 +2245,12 @@ F: hw/virtio/virtio-mem-pci.h
> F: hw/virtio/virtio-mem-pci.c
> F: include/hw/virtio/virtio-mem.h
>
> +virtio-snd
> +M: Manos Pitsidianakis <manos.pitsidianakis@linaro.org>
> +S: Supported
> +F: hw/virtio/virtio-snd*.c
> +F: include/hw/virtio/virtio-snd.h
> +
> nvme
> M: Keith Busch <kbusch@kernel.org>
> M: Klaus Jensen <its@irrelevant.dk>
> diff --git a/hw/virtio/Kconfig b/hw/virtio/Kconfig
> index 92c9cf6c96..d6f20657b3 100644
> --- a/hw/virtio/Kconfig
> +++ b/hw/virtio/Kconfig
> @@ -17,6 +17,11 @@ config VIRTIO_PCI
> depends on PCI
> select VIRTIO
>
> +config VIRTIO_SND
> + bool
> + default y
> + depends on VIRTIO
> +
> config VIRTIO_MMIO
> bool
> select VIRTIO
> diff --git a/hw/virtio/meson.build b/hw/virtio/meson.build
> index 13e7c6c272..120d4bfa0a 100644
> --- a/hw/virtio/meson.build
> +++ b/hw/virtio/meson.build
> @@ -31,6 +31,7 @@ specific_virtio_ss.add(when: 'CONFIG_VHOST_VSOCK',
> if_true: files('vhost-vsock.c
> specific_virtio_ss.add(when: 'CONFIG_VHOST_USER_VSOCK', if_true:
> files('vhost-user-vsock.c'))
> specific_virtio_ss.add(when: 'CONFIG_VIRTIO_RNG', if_true:
> files('virtio-rng.c'))
> specific_virtio_ss.add(when: 'CONFIG_VIRTIO_MEM', if_true:
> files('virtio-mem.c'))
> +specific_virtio_ss.add(when: 'CONFIG_VIRTIO_SND', if_true:
> files('virtio-snd.c'))
> specific_virtio_ss.add(when: 'CONFIG_VHOST_USER_I2C', if_true:
> files('vhost-user-i2c.c'))
> specific_virtio_ss.add(when: 'CONFIG_VHOST_USER_RNG', if_true:
> files('vhost-user-rng.c'))
> specific_virtio_ss.add(when: 'CONFIG_VHOST_USER_GPIO', if_true:
> files('vhost-user-gpio.c'))
> diff --git a/hw/virtio/trace-events b/hw/virtio/trace-events
> index 7109cf1a3b..3ed7da35f2 100644
> --- a/hw/virtio/trace-events
> +++ b/hw/virtio/trace-events
> @@ -154,3 +154,12 @@ virtio_pmem_flush_done(int type) "fsync return=%d"
> virtio_gpio_start(void) "start"
> virtio_gpio_stop(void) "stop"
> virtio_gpio_set_status(uint8_t status) "0x%x"
> +
> +#virtio-snd.c
> +virtio_snd_get_config(void *vdev, uint32_t jacks, uint32_t streams,
> uint32_t chmaps) "snd %p: get_config jacks=%"PRIu32" streams=%"PRIu32"
> chmaps=%"PRIu32""
> +virtio_snd_set_config(void *vdev, uint32_t jacks, uint32_t new_jacks,
> uint32_t streams, uint32_t new_streams, uint32_t chmaps, uint32_t
> new_chmaps) "snd %p: set_config jacks from %"PRIu32"->%"PRIu32", streams
> from %"PRIu32"->%"PRIu32", chmaps from %"PRIu32"->%"PRIu32
> +virtio_snd_get_features(void *vdev, uint64_t features) "snd %p:
> get_features 0x%"PRIx64
> +virtio_snd_vm_state_running(void) "vm state running"
> +virtio_snd_vm_state_stopped(void) "vm state stopped"
> +virtio_snd_realize(void *snd) "snd %p: realize"
> +virtio_snd_unrealize(void *snd) "snd %p: unrealize"
> diff --git a/hw/virtio/virtio-snd.c b/hw/virtio/virtio-snd.c
> new file mode 100644
> index 0000000000..e3f2156e5e
> --- /dev/null
> +++ b/hw/virtio/virtio-snd.c
> @@ -0,0 +1,230 @@
> +/*
> + * VIRTIO Sound Device conforming to
> + *
> + * "Virtual I/O Device (VIRTIO) Version 1.2
> + * Committee Specification Draft 01
> + * 09 May 2022"
> + *
> + * <
> https://docs.oasis-open.org/virtio/virtio/v1.2/csd01/virtio-v1.2-csd01.html#x1-52900014
> >
> + *
> + * Copyright (c) 2023 Emmanouil Pitsidianakis <
> manos.pitsidianakis@linaro.org>
> + * Copyright (C) 2019 OpenSynergy GmbH
> + *
> + * This work is licensed under the terms of the GNU GPL, version 2 or
> + * (at your option) any later version. See the COPYING file in the
> + * top-level directory.
> + */
> +
> +#include "qemu/osdep.h"
> +#include "qemu/iov.h"
> +#include "qemu/log.h"
> +#include "include/qemu/lockable.h"
> +#include "sysemu/runstate.h"
> +#include "trace.h"
> +#include "qapi/error.h"
> +#include "hw/virtio/virtio-snd.h"
> +
> +#define VIRTIO_SOUND_VM_VERSION 1
> +#define VIRTIO_SOUND_JACK_DEFAULT 0
> +#define VIRTIO_SOUND_STREAM_DEFAULT 1
> +#define VIRTIO_SOUND_CHMAP_DEFAULT 0
> +#define VIRTIO_SOUND_HDA_FN_NID 0
> +
> +static const VMStateDescription vmstate_virtio_snd_device = {
> + .name = TYPE_VIRTIO_SND,
> + .version_id = VIRTIO_SOUND_VM_VERSION,
> + .minimum_version_id = VIRTIO_SOUND_VM_VERSION,
> +};
> +
> +static const VMStateDescription vmstate_virtio_snd = {
> + .name = "virtio-sound",
> + .minimum_version_id = VIRTIO_SOUND_VM_VERSION,
> + .version_id = VIRTIO_SOUND_VM_VERSION,
> + .fields = (VMStateField[]) {
> + VMSTATE_VIRTIO_DEVICE,
> + VMSTATE_END_OF_LIST()
> + },
> +};
> +
> +static Property virtio_snd_properties[] = {
> + DEFINE_AUDIO_PROPERTIES(VirtIOSound, card),
> + DEFINE_PROP_UINT32("jacks", VirtIOSound, snd_conf.jacks,
> + VIRTIO_SOUND_JACK_DEFAULT),
> + DEFINE_PROP_UINT32("streams", VirtIOSound, snd_conf.streams,
> + VIRTIO_SOUND_STREAM_DEFAULT),
> + DEFINE_PROP_UINT32("chmaps", VirtIOSound, snd_conf.chmaps,
> + VIRTIO_SOUND_CHMAP_DEFAULT),
> + DEFINE_PROP_END_OF_LIST(),
> +};
> +
> +static void
> +virtio_snd_get_config(VirtIODevice *vdev, uint8_t *config)
> +{
> + VirtIOSound *s = VIRTIO_SND(vdev);
> + trace_virtio_snd_get_config(vdev,
> + s->snd_conf.jacks,
> + s->snd_conf.streams,
> + s->snd_conf.chmaps);
> +
> + memcpy(config, &s->snd_conf, sizeof(s->snd_conf));
> +}
> +
> +static void
> +virtio_snd_set_config(VirtIODevice *vdev, const uint8_t *config)
> +{
> + VirtIOSound *s = VIRTIO_SND(vdev);
> + const virtio_snd_config *sndconfig =
> + (const virtio_snd_config *)config;
> +
> +
> + trace_virtio_snd_set_config(vdev,
> + s->snd_conf.jacks,
> + sndconfig->jacks,
> + s->snd_conf.streams,
> + sndconfig->streams,
> + s->snd_conf.chmaps,
> + sndconfig->chmaps);
> +
> + memcpy(&s->snd_conf, sndconfig, sizeof(s->snd_conf));
> +}
> +
> +/*
> + * Queue handler stub.
> + *
> + * @vdev: VirtIOSound device
> + * @vq: virtqueue
> + */
> +static void virtio_snd_handle_queue(VirtIODevice *vdev, VirtQueue *vq) {}
> +
> +static uint64_t get_features(VirtIODevice *vdev, uint64_t features,
> + Error **errp)
> +{
> + /*
> + * virtio-v1.2-csd01, 5.14.3,
> + * Feature Bits
> + * None currently defined.
> + */
> + trace_virtio_snd_get_features(vdev, features);
> + return features | 1UL << VIRTIO_F_VERSION_1 | 1UL <<
> VIRTIO_F_IN_ORDER;
> +}
> +
> +static void virtio_snd_common_realize(DeviceState *dev,
> + VirtIOHandleOutput ctrl,
> + VirtIOHandleOutput evt,
> + VirtIOHandleOutput txq,
> + VirtIOHandleOutput rxq,
> + Error **errp)
> +{
> + VirtIODevice *vdev = VIRTIO_DEVICE(dev);
> + VirtIOSound *vsnd = VIRTIO_SND(dev);
> +
> + virtio_init(vdev, VIRTIO_ID_SOUND, sizeof(virtio_snd_config));
> +
> + /* set number of jacks and streams */
> + if (vsnd->snd_conf.jacks > 8) {
> + error_setg(errp,
> + "Invalid number of jacks: %"PRIu32,
> + vsnd->snd_conf.jacks);
> + return;
> + }
> + if (vsnd->snd_conf.streams < 1 || vsnd->snd_conf.streams > 10) {
> + error_setg(errp,
> + "Invalid number of streams: %"PRIu32,
> + vsnd->snd_conf.streams);
> + return;
> + }
> +
> + if (vsnd->snd_conf.chmaps > VIRTIO_SND_CHMAP_MAX_SIZE) {
> + error_setg(errp,
> + "Invalid number of channel maps: %"PRIu32,
> + vsnd->snd_conf.chmaps);
> + return;
> + }
> +
> + 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)
> +{
> + VirtIOSound *vsnd = VIRTIO_SND(dev);
> + Error *err = NULL;
> +
> + 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,
> + &err);
> + if (err != NULL) {
> + error_propagate(errp, err);
> + return;
> + }
>
if you use ERRP_GUARD() you shouldn't need this.
> +}
> +
> +static void virtio_snd_unrealize(DeviceState *dev)
> +{
> + VirtIODevice *vdev = VIRTIO_DEVICE(dev);
> + VirtIOSound *vsnd = VIRTIO_SND(dev);
> +
> + qemu_del_vm_change_state_handler(vsnd->vmstate);
> + virtio_del_queue(vdev, 0);
> +
> + trace_virtio_snd_unrealize(vsnd);
> +
> + AUD_remove_card(&vsnd->card);
> + virtio_cleanup(vdev);
> +}
> +
> +
> +static void virtio_snd_reset(VirtIODevice *vdev) {}
> +
> +static void virtio_snd_class_init(ObjectClass *klass, void *data)
> +{
> + DeviceClass *dc = DEVICE_CLASS(klass);
> + VirtioDeviceClass *vdc = VIRTIO_DEVICE_CLASS(klass);
> +
> +
> + set_bit(DEVICE_CATEGORY_SOUND, dc->categories);
> + device_class_set_props(dc, virtio_snd_properties);
> +
> + dc->vmsd = &vmstate_virtio_snd;
> + vdc->vmsd = &vmstate_virtio_snd_device;
> + vdc->realize = virtio_snd_realize;
> + vdc->unrealize = virtio_snd_unrealize;
> + vdc->get_config = virtio_snd_get_config;
> + vdc->set_config = virtio_snd_set_config;
> + vdc->get_features = get_features;
> + vdc->reset = virtio_snd_reset;
> + vdc->legacy_features = 0;
> +}
> +
> +static const TypeInfo virtio_snd_types[] = {
> + {
> + .name = TYPE_VIRTIO_SND,
> + .parent = TYPE_VIRTIO_DEVICE,
> + .instance_size = sizeof(VirtIOSound),
> + .class_init = virtio_snd_class_init,
> + }
> +};
> +
> +DEFINE_TYPES(virtio_snd_types)
> diff --git a/include/hw/virtio/virtio-snd.h
> b/include/hw/virtio/virtio-snd.h
> new file mode 100644
> index 0000000000..074b66c018
> --- /dev/null
> +++ b/include/hw/virtio/virtio-snd.h
> @@ -0,0 +1,79 @@
> +/*
> + * VIRTIO Sound Device conforming to
> + *
> + * "Virtual I/O Device (VIRTIO) Version 1.2
> + * Committee Specification Draft 01
> + * 09 May 2022"
> + *
> + * Copyright (c) 2023 Emmanouil Pitsidianakis <
> manos.pitsidianakis@linaro.org>
> + * Copyright (C) 2019 OpenSynergy GmbH
> + *
> + * This work is licensed under the terms of the GNU GPL, version 2 or
> + * (at your option) any later version. See the COPYING file in the
> + * top-level directory.
> + */
> +
> +#ifndef QEMU_VIRTIO_SOUND_H
> +#define QEMU_VIRTIO_SOUND_H
> +
> +#include "hw/virtio/virtio.h"
> +#include "audio/audio.h"
> +#include "standard-headers/linux/virtio_ids.h"
> +#include "standard-headers/linux/virtio_snd.h"
> +
> +#define TYPE_VIRTIO_SND "virtio-sound-device"
> +#define VIRTIO_SND(obj) \
> + OBJECT_CHECK(VirtIOSound, (obj), TYPE_VIRTIO_SND)
> +
> +/* CONFIGURATION SPACE */
> +
> +typedef struct virtio_snd_config virtio_snd_config;
> +
> +/* COMMON DEFINITIONS */
> +
> +/* common header for request/response*/
> +typedef struct virtio_snd_hdr virtio_snd_hdr;
> +
> +/* event notification */
> +typedef struct virtio_snd_event virtio_snd_event;
> +
> +/* common control request to query an item information */
> +typedef struct virtio_snd_query_info virtio_snd_query_info;
> +
> +/* JACK CONTROL MESSAGES */
> +
> +typedef struct virtio_snd_jack_hdr virtio_snd_jack_hdr;
> +
> +/* jack information structure */
> +typedef struct virtio_snd_jack_info virtio_snd_jack_info;
> +
> +/* jack remapping control request */
> +typedef struct virtio_snd_jack_remap virtio_snd_jack_remap;
> +
> +typedef struct virtio_snd_jack virtio_snd_jack;
> +
> +/*
> + * PCM CONTROL MESSAGES
> + */
> +typedef struct virtio_snd_pcm_hdr virtio_snd_pcm_hdr;
> +
> +/* PCM stream info structure */
> +typedef struct virtio_snd_pcm_info virtio_snd_pcm_info;
> +
> +/* set PCM stream params */
> +typedef struct virtio_snd_pcm_set_params virtio_snd_pcm_set_params;
> +
> +/* I/O request header */
> +typedef struct virtio_snd_pcm_xfer virtio_snd_pcm_xfer;
> +
> +/* I/O request status */
> +typedef struct virtio_snd_pcm_status virtio_snd_pcm_status;
> +
> +typedef struct VirtIOSound {
> + VirtIODevice parent_obj;
> + VirtQueue *queues[VIRTIO_SND_VQ_MAX];
> + QEMUSoundCard card;
> + VMChangeStateEntry *vmstate;
> + virtio_snd_config snd_conf;
> +} VirtIOSound;
> +#endif
> --
> 2.39.2
>
>
>
--
Marc-André Lureau
[-- Attachment #2: Type: text/html, Size: 17956 bytes --]
^ permalink raw reply [flat|nested] 22+ messages in thread
* Re: [PATCH v4 06/12] virtio-sound: handle VIRTIO_SND_R_PCM_INFO request
2023-07-20 12:57 ` [PATCH v4 06/12] virtio-sound: handle VIRTIO_SND_R_PCM_INFO request Emmanouil Pitsidianakis
@ 2023-07-25 14:29 ` Marc-André Lureau
2023-07-25 14:46 ` Michael S. Tsirkin
2023-07-25 14:30 ` Marc-André Lureau
1 sibling, 1 reply; 22+ messages in thread
From: Marc-André Lureau @ 2023-07-25 14:29 UTC (permalink / raw)
To: Emmanouil Pitsidianakis
Cc: qemu-devel, Igor Skalkin, Anton Yakovlev, Paolo Bonzini,
Gerd Hoffmann, Michael S. Tsirkin, Marcel Apfelbaum,
Daniel P. Berrangé, Eduardo Habkost, Volker Rümelin,
Kővágó, Zoltán, Alex Bennee,
Philippe Mathieu-Daudé
[-- Attachment #1: Type: text/plain, Size: 5364 bytes --]
On Thu, Jul 20, 2023 at 4:59 PM Emmanouil Pitsidianakis <
manos.pitsidianakis@linaro.org> wrote:
> Respond to the VIRTIO_SND_R_PCM_INFO control request with the parameters
> of each requested PCM stream.
>
> Signed-off-by: Emmanouil Pitsidianakis <manos.pitsidianakis@linaro.org>
> ---
> hw/virtio/trace-events | 1 +
> hw/virtio/virtio-snd.c | 78 ++++++++++++++++++++++++++++++++++++++++++
> 2 files changed, 79 insertions(+)
>
> diff --git a/hw/virtio/trace-events b/hw/virtio/trace-events
> index 8a223e36e9..3e619f778b 100644
> --- a/hw/virtio/trace-events
> +++ b/hw/virtio/trace-events
> @@ -164,6 +164,7 @@ virtio_snd_vm_state_stopped(void) "vm state stopped"
> virtio_snd_realize(void *snd) "snd %p: realize"
> virtio_snd_unrealize(void *snd) "snd %p: unrealize"
> virtio_snd_handle_ctrl(void *vdev, void *vq) "snd %p: handle ctrl event
> for queue %p"
> +virtio_snd_handle_pcm_info(uint32_t stream) "VIRTIO_SND_R_PCM_INFO called
> for stream %"PRIu32
> virtio_snd_handle_code(uint32_t val, const char *code) "ctrl code msg val
> = %"PRIu32" == %s"
> virtio_snd_handle_chmap_info(void) "VIRTIO_SND_CHMAP_INFO called"
> virtio_snd_handle_event(void) "event queue callback called"
> diff --git a/hw/virtio/virtio-snd.c b/hw/virtio/virtio-snd.c
> index ca09c937c7..3f8b46f372 100644
> --- a/hw/virtio/virtio-snd.c
> +++ b/hw/virtio/virtio-snd.c
> @@ -134,6 +134,19 @@ virtio_snd_set_config(VirtIODevice *vdev, const
> uint8_t *config)
> memcpy(&s->snd_conf, sndconfig, sizeof(s->snd_conf));
> }
>
> +/*
> + * Get a specific stream from the virtio sound card device.
> + * Returns NULL if @stream_id is invalid or not allocated.
> + *
> + * @s: VirtIOSound device
> + * @stream_id: stream id
> + */
> +static VirtIOSoundPCMStream *virtio_snd_pcm_get_stream(VirtIOSound *s,
> + uint32_t stream_id)
> +{
> + return stream_id >= s->snd_conf.streams ? NULL :
> s->pcm->streams[stream_id];
> +}
> +
> /*
> * Get params for a specific stream.
> *
> @@ -147,6 +160,69 @@ static VirtIOSoundPCMParams
> *virtio_snd_pcm_get_params(VirtIOSound *s,
> : s->pcm->pcm_params[stream_id];
> }
>
> +/*
> + * Handle the VIRTIO_SND_R_PCM_INFO request.
> + * The function writes the info structs to the request element.
> + *
> + * @s: VirtIOSound device
> + * @cmd: The request command queue element from VirtIOSound cmdq field
> + */
> +static void virtio_snd_handle_pcm_info(VirtIOSound *s,
> + virtio_snd_ctrl_command *cmd)
> +{
> + virtio_snd_query_info req;
> + VirtIOSoundPCMStream *stream = NULL;
> + g_autofree virtio_snd_pcm_info *pcm_info = NULL;
> + size_t sz = iov_to_buf(cmd->elem->out_sg,
> + cmd->elem->out_num,
> + 0,
> + &req,
> + sizeof(req));
> + if (sz != sizeof(virtio_snd_query_info)) {
> + cmd->resp.code = VIRTIO_SND_S_BAD_MSG;
> + return;
> + }
> +
> + if (iov_size(cmd->elem->in_sg, cmd->elem->in_num) <
> + sizeof(virtio_snd_hdr) + req.size * req.count) {
> + error_report("pcm info: buffer too small, got: %lu, needed: %lu",
> + iov_size(cmd->elem->in_sg, cmd->elem->in_num),
>
> + sizeof(virtio_snd_pcm_info));
> + cmd->resp.code = VIRTIO_SND_S_BAD_MSG;
> + return;
> + }
> +
> + pcm_info = g_new0(virtio_snd_pcm_info, req.count);
> + for (uint32_t i = req.start_id; i < req.start_id + req.count; i++) {
> + trace_virtio_snd_handle_pcm_info(i);
> + stream = virtio_snd_pcm_get_stream(s, i);
> +
> + if (!stream) {
> + error_report("Invalid stream id: %"PRIu32, i);
> + cmd->resp.code = VIRTIO_SND_S_BAD_MSG;
> + return;
> + }
> +
> + pcm_info[i - req.start_id].hdr.hda_fn_nid =
> stream->info.hdr.hda_fn_nid;
> + pcm_info[i - req.start_id].features = stream->features;
> + pcm_info[i - req.start_id].formats = stream->formats;
> + pcm_info[i - req.start_id].rates = stream->rates;
> + pcm_info[i - req.start_id].direction = stream->direction;
> + pcm_info[i - req.start_id].channels_min = stream->channels_min;
> + pcm_info[i - req.start_id].channels_max = stream->channels_max;
> +
> + memset(&pcm_info[i].padding, 0, sizeof(pcm_info[i].padding));
> + }
> +
> + cmd->resp.code = VIRTIO_SND_S_OK;
> +
> + iov_from_buf(cmd->elem->in_sg,
> + cmd->elem->in_num,
> + sizeof(virtio_snd_hdr),
> + pcm_info,
> + sizeof(virtio_snd_pcm_info) * req.count);
> +}
> +
> /*
> * Set the given stream params.
> * Called by both virtio_snd_handle_pcm_set_params and during device
> @@ -358,6 +434,8 @@ process_cmd(VirtIOSound *s, virtio_snd_ctrl_command
> *cmd)
> cmd->resp.code = VIRTIO_SND_S_NOT_SUPP;
> break;
> case VIRTIO_SND_R_PCM_INFO:
> + virtio_snd_handle_pcm_info(s, cmd);
> + break;
> case VIRTIO_SND_R_PCM_SET_PARAMS:
> case VIRTIO_SND_R_PCM_PREPARE:
> case VIRTIO_SND_R_PCM_START:
> --
> 2.39.2
>
>
>
--
Marc-André Lureau
[-- Attachment #2: Type: text/html, Size: 6804 bytes --]
^ permalink raw reply [flat|nested] 22+ messages in thread
* Re: [PATCH v4 06/12] virtio-sound: handle VIRTIO_SND_R_PCM_INFO request
2023-07-20 12:57 ` [PATCH v4 06/12] virtio-sound: handle VIRTIO_SND_R_PCM_INFO request Emmanouil Pitsidianakis
2023-07-25 14:29 ` Marc-André Lureau
@ 2023-07-25 14:30 ` Marc-André Lureau
1 sibling, 0 replies; 22+ messages in thread
From: Marc-André Lureau @ 2023-07-25 14:30 UTC (permalink / raw)
To: Emmanouil Pitsidianakis
Cc: qemu-devel, Igor Skalkin, Anton Yakovlev, Paolo Bonzini,
Gerd Hoffmann, Michael S. Tsirkin, Marcel Apfelbaum,
Daniel P. Berrangé, Eduardo Habkost, Volker Rümelin,
Kővágó, Zoltán, Alex Bennee,
Philippe Mathieu-Daudé
[-- Attachment #1: Type: text/plain, Size: 6571 bytes --]
On Thu, Jul 20, 2023 at 4:59 PM Emmanouil Pitsidianakis <
manos.pitsidianakis@linaro.org> wrote:
> Respond to the VIRTIO_SND_R_PCM_INFO control request with the parameters
> of each requested PCM stream.
>
> Signed-off-by: Emmanouil Pitsidianakis <manos.pitsidianakis@linaro.org>
> ---
> hw/virtio/trace-events | 1 +
> hw/virtio/virtio-snd.c | 78 ++++++++++++++++++++++++++++++++++++++++++
> 2 files changed, 79 insertions(+)
>
> diff --git a/hw/virtio/trace-events b/hw/virtio/trace-events
> index 8a223e36e9..3e619f778b 100644
> --- a/hw/virtio/trace-events
> +++ b/hw/virtio/trace-events
> @@ -164,6 +164,7 @@ virtio_snd_vm_state_stopped(void) "vm state stopped"
> virtio_snd_realize(void *snd) "snd %p: realize"
> virtio_snd_unrealize(void *snd) "snd %p: unrealize"
> virtio_snd_handle_ctrl(void *vdev, void *vq) "snd %p: handle ctrl event
> for queue %p"
> +virtio_snd_handle_pcm_info(uint32_t stream) "VIRTIO_SND_R_PCM_INFO called
> for stream %"PRIu32
> virtio_snd_handle_code(uint32_t val, const char *code) "ctrl code msg val
> = %"PRIu32" == %s"
> virtio_snd_handle_chmap_info(void) "VIRTIO_SND_CHMAP_INFO called"
> virtio_snd_handle_event(void) "event queue callback called"
> diff --git a/hw/virtio/virtio-snd.c b/hw/virtio/virtio-snd.c
> index ca09c937c7..3f8b46f372 100644
> --- a/hw/virtio/virtio-snd.c
> +++ b/hw/virtio/virtio-snd.c
> @@ -134,6 +134,19 @@ virtio_snd_set_config(VirtIODevice *vdev, const
> uint8_t *config)
> memcpy(&s->snd_conf, sndconfig, sizeof(s->snd_conf));
> }
>
> +/*
> + * Get a specific stream from the virtio sound card device.
> + * Returns NULL if @stream_id is invalid or not allocated.
> + *
> + * @s: VirtIOSound device
> + * @stream_id: stream id
> + */
> +static VirtIOSoundPCMStream *virtio_snd_pcm_get_stream(VirtIOSound *s,
> + uint32_t stream_id)
> +{
> + return stream_id >= s->snd_conf.streams ? NULL :
> s->pcm->streams[stream_id];
> +}
> +
> /*
> * Get params for a specific stream.
> *
> @@ -147,6 +160,69 @@ static VirtIOSoundPCMParams
> *virtio_snd_pcm_get_params(VirtIOSound *s,
> : s->pcm->pcm_params[stream_id];
> }
>
> +/*
> + * Handle the VIRTIO_SND_R_PCM_INFO request.
> + * The function writes the info structs to the request element.
> + *
> + * @s: VirtIOSound device
> + * @cmd: The request command queue element from VirtIOSound cmdq field
> + */
> +static void virtio_snd_handle_pcm_info(VirtIOSound *s,
> + virtio_snd_ctrl_command *cmd)
> +{
> + virtio_snd_query_info req;
> + VirtIOSoundPCMStream *stream = NULL;
> + g_autofree virtio_snd_pcm_info *pcm_info = NULL;
> + size_t sz = iov_to_buf(cmd->elem->out_sg,
> + cmd->elem->out_num,
> + 0,
> + &req,
> + sizeof(req));
> + if (sz != sizeof(virtio_snd_query_info)) {
> + cmd->resp.code = VIRTIO_SND_S_BAD_MSG;
> + return;
> + }
> +
> + if (iov_size(cmd->elem->in_sg, cmd->elem->in_num) <
> + sizeof(virtio_snd_hdr) + req.size * req.count) {
> + error_report("pcm info: buffer too small, got: %lu, needed: %lu",
> + iov_size(cmd->elem->in_sg, cmd->elem->in_num),
> + sizeof(virtio_snd_pcm_info));
>
../hw/virtio/virtio-snd.c: In function 'virtio_snd_handle_pcm_info':
../hw/virtio/virtio-snd.c:200:22: error: format '%lu' expects argument of
type 'long unsigned int', but argument 2 has type 'size_t' {aka 'long long
unsigned int'} [-Werror=format=]
200 | error_report("pcm info: buffer too small, got: %lu, needed:
%lu",
|
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
201 | iov_size(cmd->elem->in_sg, cmd->elem->in_num),
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
| |
| size_t {aka long long unsigned int}
../hw/virtio/virtio-snd.c:200:22: error: format '%lu' expects argument of
type 'long unsigned int', but argument 3 has type 'long long unsigned int'
[-Werror=format=]
200 | error_report("pcm info: buffer too small, got: %lu, needed:
%lu",
|
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
201 | iov_size(cmd->elem->in_sg, cmd->elem->in_num),
202 | sizeof(virtio_snd_pcm_info));
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~
| |
| long long unsigned int
> + cmd->resp.code = VIRTIO_SND_S_BAD_MSG;
> + return;
> + }
> +
> + pcm_info = g_new0(virtio_snd_pcm_info, req.count);
> + for (uint32_t i = req.start_id; i < req.start_id + req.count; i++) {
> + trace_virtio_snd_handle_pcm_info(i);
> + stream = virtio_snd_pcm_get_stream(s, i);
> +
> + if (!stream) {
> + error_report("Invalid stream id: %"PRIu32, i);
> + cmd->resp.code = VIRTIO_SND_S_BAD_MSG;
> + return;
> + }
> +
> + pcm_info[i - req.start_id].hdr.hda_fn_nid =
> stream->info.hdr.hda_fn_nid;
> + pcm_info[i - req.start_id].features = stream->features;
> + pcm_info[i - req.start_id].formats = stream->formats;
> + pcm_info[i - req.start_id].rates = stream->rates;
> + pcm_info[i - req.start_id].direction = stream->direction;
> + pcm_info[i - req.start_id].channels_min = stream->channels_min;
> + pcm_info[i - req.start_id].channels_max = stream->channels_max;
> +
> + memset(&pcm_info[i].padding, 0, sizeof(pcm_info[i].padding));
> + }
> +
> + cmd->resp.code = VIRTIO_SND_S_OK;
> +
> + iov_from_buf(cmd->elem->in_sg,
> + cmd->elem->in_num,
> + sizeof(virtio_snd_hdr),
> + pcm_info,
> + sizeof(virtio_snd_pcm_info) * req.count);
> +}
> +
> /*
> * Set the given stream params.
> * Called by both virtio_snd_handle_pcm_set_params and during device
> @@ -358,6 +434,8 @@ process_cmd(VirtIOSound *s, virtio_snd_ctrl_command
> *cmd)
> cmd->resp.code = VIRTIO_SND_S_NOT_SUPP;
> break;
> case VIRTIO_SND_R_PCM_INFO:
> + virtio_snd_handle_pcm_info(s, cmd);
> + break;
> case VIRTIO_SND_R_PCM_SET_PARAMS:
> case VIRTIO_SND_R_PCM_PREPARE:
> case VIRTIO_SND_R_PCM_START:
> --
> 2.39.2
>
>
>
--
Marc-André Lureau
[-- Attachment #2: Type: text/html, Size: 8338 bytes --]
^ permalink raw reply [flat|nested] 22+ messages in thread
* Re: [PATCH v4 01/12] Add virtio-sound device stub
2023-07-20 12:57 ` [PATCH v4 01/12] Add virtio-sound device stub Emmanouil Pitsidianakis
2023-07-25 14:22 ` Marc-André Lureau
@ 2023-07-25 14:31 ` Marc-André Lureau
2023-07-25 14:50 ` Michael S. Tsirkin
1 sibling, 1 reply; 22+ messages in thread
From: Marc-André Lureau @ 2023-07-25 14:31 UTC (permalink / raw)
To: Emmanouil Pitsidianakis
Cc: qemu-devel, Igor Skalkin, Anton Yakovlev, Paolo Bonzini,
Gerd Hoffmann, Michael S. Tsirkin, Marcel Apfelbaum,
Daniel P. Berrangé, Eduardo Habkost, Volker Rümelin,
Kővágó, Zoltán, Alex Bennee,
Philippe Mathieu-Daudé
[-- Attachment #1: Type: text/plain, Size: 8261 bytes --]
Hi
On Thu, Jul 20, 2023 at 4:58 PM Emmanouil Pitsidianakis <
manos.pitsidianakis@linaro.org> wrote:
> Add a new VIRTIO device for the virtio sound device id. Functionality
> will be added in the following commits.
>
> Signed-off-by: Emmanouil Pitsidianakis <manos.pitsidianakis@linaro.org>
> ---
> MAINTAINERS | 6 +
> hw/virtio/Kconfig | 5 +
> hw/virtio/meson.build | 1 +
> hw/virtio/trace-events | 9 ++
> hw/virtio/virtio-snd.c | 230 +++++++++++++++++++++++++++++++++
> include/hw/virtio/virtio-snd.h | 79 +++++++++++
> 6 files changed, 330 insertions(+)
> create mode 100644 hw/virtio/virtio-snd.c
> create mode 100644 include/hw/virtio/virtio-snd.h
>
> diff --git a/MAINTAINERS b/MAINTAINERS
> index 12e59b6b27..2bed60f9c1 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -2245,6 +2245,12 @@ F: hw/virtio/virtio-mem-pci.h
> F: hw/virtio/virtio-mem-pci.c
> F: include/hw/virtio/virtio-mem.h
>
> +virtio-snd
> +M: Manos Pitsidianakis <manos.pitsidianakis@linaro.org>
> +S: Supported
> +F: hw/virtio/virtio-snd*.c
> +F: include/hw/virtio/virtio-snd.h
> +
> nvme
> M: Keith Busch <kbusch@kernel.org>
> M: Klaus Jensen <its@irrelevant.dk>
> diff --git a/hw/virtio/Kconfig b/hw/virtio/Kconfig
> index 92c9cf6c96..d6f20657b3 100644
> --- a/hw/virtio/Kconfig
> +++ b/hw/virtio/Kconfig
> @@ -17,6 +17,11 @@ config VIRTIO_PCI
> depends on PCI
> select VIRTIO
>
> +config VIRTIO_SND
> + bool
> + default y
> + depends on VIRTIO
> +
> config VIRTIO_MMIO
> bool
> select VIRTIO
> diff --git a/hw/virtio/meson.build b/hw/virtio/meson.build
> index 13e7c6c272..120d4bfa0a 100644
> --- a/hw/virtio/meson.build
> +++ b/hw/virtio/meson.build
> @@ -31,6 +31,7 @@ specific_virtio_ss.add(when: 'CONFIG_VHOST_VSOCK',
> if_true: files('vhost-vsock.c
> specific_virtio_ss.add(when: 'CONFIG_VHOST_USER_VSOCK', if_true:
> files('vhost-user-vsock.c'))
> specific_virtio_ss.add(when: 'CONFIG_VIRTIO_RNG', if_true:
> files('virtio-rng.c'))
> specific_virtio_ss.add(when: 'CONFIG_VIRTIO_MEM', if_true:
> files('virtio-mem.c'))
> +specific_virtio_ss.add(when: 'CONFIG_VIRTIO_SND', if_true:
> files('virtio-snd.c'))
> specific_virtio_ss.add(when: 'CONFIG_VHOST_USER_I2C', if_true:
> files('vhost-user-i2c.c'))
> specific_virtio_ss.add(when: 'CONFIG_VHOST_USER_RNG', if_true:
> files('vhost-user-rng.c'))
> specific_virtio_ss.add(when: 'CONFIG_VHOST_USER_GPIO', if_true:
> files('vhost-user-gpio.c'))
> diff --git a/hw/virtio/trace-events b/hw/virtio/trace-events
> index 7109cf1a3b..3ed7da35f2 100644
> --- a/hw/virtio/trace-events
> +++ b/hw/virtio/trace-events
> @@ -154,3 +154,12 @@ virtio_pmem_flush_done(int type) "fsync return=%d"
> virtio_gpio_start(void) "start"
> virtio_gpio_stop(void) "stop"
> virtio_gpio_set_status(uint8_t status) "0x%x"
> +
> +#virtio-snd.c
> +virtio_snd_get_config(void *vdev, uint32_t jacks, uint32_t streams,
> uint32_t chmaps) "snd %p: get_config jacks=%"PRIu32" streams=%"PRIu32"
> chmaps=%"PRIu32""
> +virtio_snd_set_config(void *vdev, uint32_t jacks, uint32_t new_jacks,
> uint32_t streams, uint32_t new_streams, uint32_t chmaps, uint32_t
> new_chmaps) "snd %p: set_config jacks from %"PRIu32"->%"PRIu32", streams
> from %"PRIu32"->%"PRIu32", chmaps from %"PRIu32"->%"PRIu32
> +virtio_snd_get_features(void *vdev, uint64_t features) "snd %p:
> get_features 0x%"PRIx64
> +virtio_snd_vm_state_running(void) "vm state running"
> +virtio_snd_vm_state_stopped(void) "vm state stopped"
> +virtio_snd_realize(void *snd) "snd %p: realize"
> +virtio_snd_unrealize(void *snd) "snd %p: unrealize"
> diff --git a/hw/virtio/virtio-snd.c b/hw/virtio/virtio-snd.c
> new file mode 100644
> index 0000000000..e3f2156e5e
> --- /dev/null
> +++ b/hw/virtio/virtio-snd.c
> @@ -0,0 +1,230 @@
> +/*
> + * VIRTIO Sound Device conforming to
> + *
> + * "Virtual I/O Device (VIRTIO) Version 1.2
> + * Committee Specification Draft 01
> + * 09 May 2022"
> + *
> + * <
> https://docs.oasis-open.org/virtio/virtio/v1.2/csd01/virtio-v1.2-csd01.html#x1-52900014
> >
> + *
> + * Copyright (c) 2023 Emmanouil Pitsidianakis <
> manos.pitsidianakis@linaro.org>
> + * Copyright (C) 2019 OpenSynergy GmbH
> + *
> + * This work is licensed under the terms of the GNU GPL, version 2 or
> + * (at your option) any later version. See the COPYING file in the
> + * top-level directory.
> + */
> +
> +#include "qemu/osdep.h"
> +#include "qemu/iov.h"
> +#include "qemu/log.h"
> +#include "include/qemu/lockable.h"
> +#include "sysemu/runstate.h"
> +#include "trace.h"
> +#include "qapi/error.h"
> +#include "hw/virtio/virtio-snd.h"
> +
> +#define VIRTIO_SOUND_VM_VERSION 1
> +#define VIRTIO_SOUND_JACK_DEFAULT 0
> +#define VIRTIO_SOUND_STREAM_DEFAULT 1
> +#define VIRTIO_SOUND_CHMAP_DEFAULT 0
> +#define VIRTIO_SOUND_HDA_FN_NID 0
> +
> +static const VMStateDescription vmstate_virtio_snd_device = {
> + .name = TYPE_VIRTIO_SND,
> + .version_id = VIRTIO_SOUND_VM_VERSION,
> + .minimum_version_id = VIRTIO_SOUND_VM_VERSION,
> +};
> +
> +static const VMStateDescription vmstate_virtio_snd = {
> + .name = "virtio-sound",
> + .minimum_version_id = VIRTIO_SOUND_VM_VERSION,
> + .version_id = VIRTIO_SOUND_VM_VERSION,
> + .fields = (VMStateField[]) {
> + VMSTATE_VIRTIO_DEVICE,
> + VMSTATE_END_OF_LIST()
> + },
> +};
> +
> +static Property virtio_snd_properties[] = {
> + DEFINE_AUDIO_PROPERTIES(VirtIOSound, card),
> + DEFINE_PROP_UINT32("jacks", VirtIOSound, snd_conf.jacks,
> + VIRTIO_SOUND_JACK_DEFAULT),
> + DEFINE_PROP_UINT32("streams", VirtIOSound, snd_conf.streams,
> + VIRTIO_SOUND_STREAM_DEFAULT),
> + DEFINE_PROP_UINT32("chmaps", VirtIOSound, snd_conf.chmaps,
> + VIRTIO_SOUND_CHMAP_DEFAULT),
> + DEFINE_PROP_END_OF_LIST(),
> +};
> +
> +static void
> +virtio_snd_get_config(VirtIODevice *vdev, uint8_t *config)
> +{
> + VirtIOSound *s = VIRTIO_SND(vdev);
> + trace_virtio_snd_get_config(vdev,
> + s->snd_conf.jacks,
> + s->snd_conf.streams,
> + s->snd_conf.chmaps);
> +
> + memcpy(config, &s->snd_conf, sizeof(s->snd_conf));
> +}
> +
> +static void
> +virtio_snd_set_config(VirtIODevice *vdev, const uint8_t *config)
> +{
> + VirtIOSound *s = VIRTIO_SND(vdev);
> + const virtio_snd_config *sndconfig =
> + (const virtio_snd_config *)config;
> +
> +
> + trace_virtio_snd_set_config(vdev,
> + s->snd_conf.jacks,
> + sndconfig->jacks,
> + s->snd_conf.streams,
> + sndconfig->streams,
> + s->snd_conf.chmaps,
> + sndconfig->chmaps);
> +
> + memcpy(&s->snd_conf, sndconfig, sizeof(s->snd_conf));
> +}
> +
> +/*
> + * Queue handler stub.
> + *
> + * @vdev: VirtIOSound device
> + * @vq: virtqueue
> + */
> +static void virtio_snd_handle_queue(VirtIODevice *vdev, VirtQueue *vq) {}
> +
> +static uint64_t get_features(VirtIODevice *vdev, uint64_t features,
> + Error **errp)
> +{
> + /*
> + * virtio-v1.2-csd01, 5.14.3,
> + * Feature Bits
> + * None currently defined.
> + */
> + trace_virtio_snd_get_features(vdev, features);
> + return features | 1UL << VIRTIO_F_VERSION_1 | 1UL <<
> VIRTIO_F_IN_ORDER;
>
../hw/virtio/virtio-snd.c: In function 'get_features':
../hw/virtio/virtio-snd.c:883:27: error: left shift count >= width of type
[-Werror=shift-count-overflow]
883 | return features | 1UL << VIRTIO_F_VERSION_1 | 1UL <<
VIRTIO_F_IN_ORDER;
| ^~
../hw/virtio/virtio-snd.c:883:55: error: left shift count >= width of type
[-Werror=shift-count-overflow]
883 | return features | 1UL << VIRTIO_F_VERSION_1 | 1UL <<
VIRTIO_F_IN_ORDER;
| ^~
--
Marc-André Lureau
[-- Attachment #2: Type: text/html, Size: 10461 bytes --]
^ permalink raw reply [flat|nested] 22+ messages in thread
* Re: [PATCH v4 06/12] virtio-sound: handle VIRTIO_SND_R_PCM_INFO request
2023-07-25 14:29 ` Marc-André Lureau
@ 2023-07-25 14:46 ` Michael S. Tsirkin
2023-07-25 14:54 ` Marc-André Lureau
0 siblings, 1 reply; 22+ messages in thread
From: Michael S. Tsirkin @ 2023-07-25 14:46 UTC (permalink / raw)
To: Marc-André Lureau
Cc: Emmanouil Pitsidianakis, qemu-devel, Igor Skalkin, Anton Yakovlev,
Paolo Bonzini, Gerd Hoffmann, Marcel Apfelbaum,
Daniel P. Berrangé, Eduardo Habkost, Volker Rümelin,
Kővágó, Zoltán, Alex Bennee,
Philippe Mathieu-Daudé
On Tue, Jul 25, 2023 at 06:29:58PM +0400, Marc-André Lureau wrote:
>
>
> On Thu, Jul 20, 2023 at 4:59 PM Emmanouil Pitsidianakis <
> manos.pitsidianakis@linaro.org> wrote:
>
> Respond to the VIRTIO_SND_R_PCM_INFO control request with the parameters
> of each requested PCM stream.
>
> Signed-off-by: Emmanouil Pitsidianakis <manos.pitsidianakis@linaro.org>
> ---
> hw/virtio/trace-events | 1 +
> hw/virtio/virtio-snd.c | 78 ++++++++++++++++++++++++++++++++++++++++++
> 2 files changed, 79 insertions(+)
>
> diff --git a/hw/virtio/trace-events b/hw/virtio/trace-events
> index 8a223e36e9..3e619f778b 100644
> --- a/hw/virtio/trace-events
> +++ b/hw/virtio/trace-events
> @@ -164,6 +164,7 @@ virtio_snd_vm_state_stopped(void) "vm state stopped"
> virtio_snd_realize(void *snd) "snd %p: realize"
> virtio_snd_unrealize(void *snd) "snd %p: unrealize"
> virtio_snd_handle_ctrl(void *vdev, void *vq) "snd %p: handle ctrl event
> for queue %p"
> +virtio_snd_handle_pcm_info(uint32_t stream) "VIRTIO_SND_R_PCM_INFO called
> for stream %"PRIu32
> virtio_snd_handle_code(uint32_t val, const char *code) "ctrl code msg val
> = %"PRIu32" == %s"
> virtio_snd_handle_chmap_info(void) "VIRTIO_SND_CHMAP_INFO called"
> virtio_snd_handle_event(void) "event queue callback called"
> diff --git a/hw/virtio/virtio-snd.c b/hw/virtio/virtio-snd.c
> index ca09c937c7..3f8b46f372 100644
> --- a/hw/virtio/virtio-snd.c
> +++ b/hw/virtio/virtio-snd.c
> @@ -134,6 +134,19 @@ virtio_snd_set_config(VirtIODevice *vdev, const
> uint8_t *config)
> memcpy(&s->snd_conf, sndconfig, sizeof(s->snd_conf));
> }
>
> +/*
> + * Get a specific stream from the virtio sound card device.
> + * Returns NULL if @stream_id is invalid or not allocated.
> + *
> + * @s: VirtIOSound device
> + * @stream_id: stream id
> + */
> +static VirtIOSoundPCMStream *virtio_snd_pcm_get_stream(VirtIOSound *s,
> + uint32_t stream_id)
> +{
> + return stream_id >= s->snd_conf.streams ? NULL : s->pcm->streams
> [stream_id];
> +}
> +
> /*
> * Get params for a specific stream.
> *
> @@ -147,6 +160,69 @@ static VirtIOSoundPCMParams *virtio_snd_pcm_get_params
> (VirtIOSound *s,
> : s->pcm->pcm_params[stream_id];
> }
>
> +/*
> + * Handle the VIRTIO_SND_R_PCM_INFO request.
> + * The function writes the info structs to the request element.
> + *
> + * @s: VirtIOSound device
> + * @cmd: The request command queue element from VirtIOSound cmdq field
> + */
> +static void virtio_snd_handle_pcm_info(VirtIOSound *s,
> + virtio_snd_ctrl_command *cmd)
> +{
> + virtio_snd_query_info req;
> + VirtIOSoundPCMStream *stream = NULL;
> + g_autofree virtio_snd_pcm_info *pcm_info = NULL;
> + size_t sz = iov_to_buf(cmd->elem->out_sg,
> + cmd->elem->out_num,
> + 0,
> + &req,
> + sizeof(req));
> + if (sz != sizeof(virtio_snd_query_info)) {
> + cmd->resp.code = VIRTIO_SND_S_BAD_MSG;
> + return;
> + }
> +
> + if (iov_size(cmd->elem->in_sg, cmd->elem->in_num) <
> + sizeof(virtio_snd_hdr) + req.size * req.count) {
> + error_report("pcm info: buffer too small, got: %lu, needed: %lu",
> + iov_size(cmd->elem->in_sg, cmd->elem->in_num),
>
>
>
> + sizeof(virtio_snd_pcm_info));
> + cmd->resp.code = VIRTIO_SND_S_BAD_MSG;
> + return;
> + }
> +
> + pcm_info = g_new0(virtio_snd_pcm_info, req.count);
> + for (uint32_t i = req.start_id; i < req.start_id + req.count; i++) {
> + trace_virtio_snd_handle_pcm_info(i);
> + stream = virtio_snd_pcm_get_stream(s, i);
> +
> + if (!stream) {
> + error_report("Invalid stream id: %"PRIu32, i);
> + cmd->resp.code = VIRTIO_SND_S_BAD_MSG;
> + return;
> + }
> +
> + pcm_info[i - req.start_id].hdr.hda_fn_nid = stream->
> info.hdr.hda_fn_nid;
> + pcm_info[i - req.start_id].features = stream->features;
> + pcm_info[i - req.start_id].formats = stream->formats;
> + pcm_info[i - req.start_id].rates = stream->rates;
> + pcm_info[i - req.start_id].direction = stream->direction;
> + pcm_info[i - req.start_id].channels_min = stream->channels_min;
> + pcm_info[i - req.start_id].channels_max = stream->channels_max;
> +
> + memset(&pcm_info[i].padding, 0, sizeof(pcm_info[i].padding));
> + }
> +
> + cmd->resp.code = VIRTIO_SND_S_OK;
> +
> + iov_from_buf(cmd->elem->in_sg,
> + cmd->elem->in_num,
> + sizeof(virtio_snd_hdr),
> + pcm_info,
> + sizeof(virtio_snd_pcm_info) * req.count);
> +}
> +
> /*
> * Set the given stream params.
> * Called by both virtio_snd_handle_pcm_set_params and during device
> @@ -358,6 +434,8 @@ process_cmd(VirtIOSound *s, virtio_snd_ctrl_command
> *cmd)
> cmd->resp.code = VIRTIO_SND_S_NOT_SUPP;
> break;
> case VIRTIO_SND_R_PCM_INFO:
> + virtio_snd_handle_pcm_info(s, cmd);
> + break;
> case VIRTIO_SND_R_PCM_SET_PARAMS:
> case VIRTIO_SND_R_PCM_PREPARE:
> case VIRTIO_SND_R_PCM_START:
> --
> 2.39.2
>
>
>
Marc-André can you please stop with trying to use gmail web client?
Look here to see how it corrupts text by wrapping lines:
https://lore.kernel.org/all/CAJ+F1C+H+82cA=mhpju-2nxRSA3BWnWJmp4-pi+G=Lsri0oGTw@mail.gmail.com/
And please cut out irrelevant parts of message - I've no idea what you tried to say here.
--
MST
^ permalink raw reply [flat|nested] 22+ messages in thread
* Re: [PATCH v4 01/12] Add virtio-sound device stub
2023-07-25 14:31 ` Marc-André Lureau
@ 2023-07-25 14:50 ` Michael S. Tsirkin
0 siblings, 0 replies; 22+ messages in thread
From: Michael S. Tsirkin @ 2023-07-25 14:50 UTC (permalink / raw)
To: Marc-André Lureau
Cc: Emmanouil Pitsidianakis, qemu-devel, Igor Skalkin, Anton Yakovlev,
Paolo Bonzini, Gerd Hoffmann, Marcel Apfelbaum,
Daniel P. Berrangé, Eduardo Habkost, Volker Rümelin,
Kővágó, Zoltán, Alex Bennee,
Philippe Mathieu-Daudé
> +static uint64_t get_features(VirtIODevice *vdev, uint64_t features,
> + Error **errp)
> +{
> + /*
> + * virtio-v1.2-csd01, 5.14.3,
> + * Feature Bits
> + * None currently defined.
> + */
> + trace_virtio_snd_get_features(vdev, features);
> + return features | 1UL << VIRTIO_F_VERSION_1 | 1UL <<
> VIRTIO_F_IN_ORDER;
>
>
> ../hw/virtio/virtio-snd.c: In function 'get_features':
> ../hw/virtio/virtio-snd.c:883:27: error: left shift count >= width of type
> [-Werror=shift-count-overflow]
> 883 | return features | 1UL << VIRTIO_F_VERSION_1 | 1UL <<
> VIRTIO_F_IN_ORDER;
> | ^~
> ../hw/virtio/virtio-snd.c:883:55: error: left shift count >= width of type
> [-Werror=shift-count-overflow]
> 883 | return features | 1UL << VIRTIO_F_VERSION_1 | 1UL <<
> VIRTIO_F_IN_ORDER;
> | ^~
>
Same.
https://lore.kernel.org/all/CAJ+F1CJdbcsdHu8WmiDDS_q7ddcJ6RPOLe2XH_EBQkqJTtMw-Q@mail.gmail.com/
Pls use a different client
and pls only quote relevant part of message.
--
MST
^ permalink raw reply [flat|nested] 22+ messages in thread
* Re: [PATCH v4 06/12] virtio-sound: handle VIRTIO_SND_R_PCM_INFO request
2023-07-25 14:46 ` Michael S. Tsirkin
@ 2023-07-25 14:54 ` Marc-André Lureau
2023-07-25 16:15 ` Michael S. Tsirkin
0 siblings, 1 reply; 22+ messages in thread
From: Marc-André Lureau @ 2023-07-25 14:54 UTC (permalink / raw)
To: Michael S. Tsirkin
Cc: Emmanouil Pitsidianakis, qemu-devel, Igor Skalkin, Anton Yakovlev,
Paolo Bonzini, Gerd Hoffmann, Marcel Apfelbaum,
Daniel P. Berrangé, Eduardo Habkost, Volker Rümelin,
Kővágó, Zoltán, Alex Bennee,
Philippe Mathieu-Daudé
[-- Attachment #1: Type: text/plain, Size: 6888 bytes --]
Hi
On Tue, Jul 25, 2023 at 6:47 PM Michael S. Tsirkin <mst@redhat.com> wrote:
> On Tue, Jul 25, 2023 at 06:29:58PM +0400, Marc-André Lureau wrote:
> >
> >
> > On Thu, Jul 20, 2023 at 4:59 PM Emmanouil Pitsidianakis <
> > manos.pitsidianakis@linaro.org> wrote:
> >
> > Respond to the VIRTIO_SND_R_PCM_INFO control request with the
> parameters
> > of each requested PCM stream.
> >
> > Signed-off-by: Emmanouil Pitsidianakis <
> manos.pitsidianakis@linaro.org>
> > ---
> > hw/virtio/trace-events | 1 +
> > hw/virtio/virtio-snd.c | 78
> ++++++++++++++++++++++++++++++++++++++++++
> > 2 files changed, 79 insertions(+)
> >
> > diff --git a/hw/virtio/trace-events b/hw/virtio/trace-events
> > index 8a223e36e9..3e619f778b 100644
> > --- a/hw/virtio/trace-events
> > +++ b/hw/virtio/trace-events
> > @@ -164,6 +164,7 @@ virtio_snd_vm_state_stopped(void) "vm state
> stopped"
> > virtio_snd_realize(void *snd) "snd %p: realize"
> > virtio_snd_unrealize(void *snd) "snd %p: unrealize"
> > virtio_snd_handle_ctrl(void *vdev, void *vq) "snd %p: handle ctrl
> event
> > for queue %p"
> > +virtio_snd_handle_pcm_info(uint32_t stream) "VIRTIO_SND_R_PCM_INFO
> called
> > for stream %"PRIu32
> > virtio_snd_handle_code(uint32_t val, const char *code) "ctrl code
> msg val
> > = %"PRIu32" == %s"
> > virtio_snd_handle_chmap_info(void) "VIRTIO_SND_CHMAP_INFO called"
> > virtio_snd_handle_event(void) "event queue callback called"
> > diff --git a/hw/virtio/virtio-snd.c b/hw/virtio/virtio-snd.c
> > index ca09c937c7..3f8b46f372 100644
> > --- a/hw/virtio/virtio-snd.c
> > +++ b/hw/virtio/virtio-snd.c
> > @@ -134,6 +134,19 @@ virtio_snd_set_config(VirtIODevice *vdev, const
> > uint8_t *config)
> > memcpy(&s->snd_conf, sndconfig, sizeof(s->snd_conf));
> > }
> >
> > +/*
> > + * Get a specific stream from the virtio sound card device.
> > + * Returns NULL if @stream_id is invalid or not allocated.
> > + *
> > + * @s: VirtIOSound device
> > + * @stream_id: stream id
> > + */
> > +static VirtIOSoundPCMStream *virtio_snd_pcm_get_stream(VirtIOSound
> *s,
> > + uint32_t
> stream_id)
> > +{
> > + return stream_id >= s->snd_conf.streams ? NULL : s->pcm->streams
> > [stream_id];
> > +}
> > +
> > /*
> > * Get params for a specific stream.
> > *
> > @@ -147,6 +160,69 @@ static VirtIOSoundPCMParams
> *virtio_snd_pcm_get_params
> > (VirtIOSound *s,
> > : s->pcm->pcm_params[stream_id];
> > }
> >
> > +/*
> > + * Handle the VIRTIO_SND_R_PCM_INFO request.
> > + * The function writes the info structs to the request element.
> > + *
> > + * @s: VirtIOSound device
> > + * @cmd: The request command queue element from VirtIOSound cmdq
> field
> > + */
> > +static void virtio_snd_handle_pcm_info(VirtIOSound *s,
> > + virtio_snd_ctrl_command *cmd)
> > +{
> > + virtio_snd_query_info req;
> > + VirtIOSoundPCMStream *stream = NULL;
> > + g_autofree virtio_snd_pcm_info *pcm_info = NULL;
> > + size_t sz = iov_to_buf(cmd->elem->out_sg,
> > + cmd->elem->out_num,
> > + 0,
> > + &req,
> > + sizeof(req));
> > + if (sz != sizeof(virtio_snd_query_info)) {
> > + cmd->resp.code = VIRTIO_SND_S_BAD_MSG;
> > + return;
> > + }
> > +
> > + if (iov_size(cmd->elem->in_sg, cmd->elem->in_num) <
> > + sizeof(virtio_snd_hdr) + req.size * req.count) {
> > + error_report("pcm info: buffer too small, got: %lu, needed:
> %lu",
> > + iov_size(cmd->elem->in_sg, cmd->elem->in_num),
> >
> >
> >
> > + sizeof(virtio_snd_pcm_info));
> > + cmd->resp.code = VIRTIO_SND_S_BAD_MSG;
> > + return;
> > + }
> > +
> > + pcm_info = g_new0(virtio_snd_pcm_info, req.count);
> > + for (uint32_t i = req.start_id; i < req.start_id + req.count;
> i++) {
> > + trace_virtio_snd_handle_pcm_info(i);
> > + stream = virtio_snd_pcm_get_stream(s, i);
> > +
> > + if (!stream) {
> > + error_report("Invalid stream id: %"PRIu32, i);
> > + cmd->resp.code = VIRTIO_SND_S_BAD_MSG;
> > + return;
> > + }
> > +
> > + pcm_info[i - req.start_id].hdr.hda_fn_nid = stream->
> > info.hdr.hda_fn_nid;
> > + pcm_info[i - req.start_id].features = stream->features;
> > + pcm_info[i - req.start_id].formats = stream->formats;
> > + pcm_info[i - req.start_id].rates = stream->rates;
> > + pcm_info[i - req.start_id].direction = stream->direction;
> > + pcm_info[i - req.start_id].channels_min =
> stream->channels_min;
> > + pcm_info[i - req.start_id].channels_max =
> stream->channels_max;
> > +
> > + memset(&pcm_info[i].padding, 0,
> sizeof(pcm_info[i].padding));
> > + }
> > +
> > + cmd->resp.code = VIRTIO_SND_S_OK;
> > +
> > + iov_from_buf(cmd->elem->in_sg,
> > + cmd->elem->in_num,
> > + sizeof(virtio_snd_hdr),
> > + pcm_info,
> > + sizeof(virtio_snd_pcm_info) * req.count);
> > +}
> > +
> > /*
> > * Set the given stream params.
> > * Called by both virtio_snd_handle_pcm_set_params and during device
> > @@ -358,6 +434,8 @@ process_cmd(VirtIOSound *s,
> virtio_snd_ctrl_command
> > *cmd)
> > cmd->resp.code = VIRTIO_SND_S_NOT_SUPP;
> > break;
> > case VIRTIO_SND_R_PCM_INFO:
> > + virtio_snd_handle_pcm_info(s, cmd);
> > + break;
> > case VIRTIO_SND_R_PCM_SET_PARAMS:
> > case VIRTIO_SND_R_PCM_PREPARE:
> > case VIRTIO_SND_R_PCM_START:
> > --
> > 2.39.2
> >
> >
> >
>
>
> Marc-André can you please stop with trying to use gmail web client?
>
Trying? I think I have almost exclusively used it over the past 15y or so :)
> Look here to see how it corrupts text by wrapping lines:
>
> https://lore.kernel.org/all/CAJ+F1C+H+82cA=mhpju-2nxRSA3BWnWJmp4-pi+G=Lsri0oGTw@mail.gmail.com/
>
> And please cut out irrelevant parts of message - I've no idea what you
> tried to say here.
>
that was my mistake, I sent it too quickly.. it happens.
--
Marc-André Lureau
[-- Attachment #2: Type: text/html, Size: 9430 bytes --]
^ permalink raw reply [flat|nested] 22+ messages in thread
* Re: [PATCH v4 06/12] virtio-sound: handle VIRTIO_SND_R_PCM_INFO request
2023-07-25 14:54 ` Marc-André Lureau
@ 2023-07-25 16:15 ` Michael S. Tsirkin
0 siblings, 0 replies; 22+ messages in thread
From: Michael S. Tsirkin @ 2023-07-25 16:15 UTC (permalink / raw)
To: Marc-André Lureau
Cc: Emmanouil Pitsidianakis, qemu-devel, Igor Skalkin, Anton Yakovlev,
Paolo Bonzini, Gerd Hoffmann, Marcel Apfelbaum,
Daniel P. Berrangé, Eduardo Habkost, Volker Rümelin,
Kővágó, Zoltán, Alex Bennee,
Philippe Mathieu-Daudé
On Tue, Jul 25, 2023 at 06:54:56PM +0400, Marc-André Lureau wrote:
>
> Marc-André can you please stop with trying to use gmail web client?
>
>
> Trying? I think I have almost exclusively used it over the past 15y or so :)
>
Then find a way make it not wrap lines. The result of corrupted text is
people giving up in disgust and asking everyone to switch to gitlab
or slack or whatnot.
--
MST
^ permalink raw reply [flat|nested] 22+ messages in thread
end of thread, other threads:[~2023-07-25 16:15 UTC | newest]
Thread overview: 22+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2023-07-20 12:57 [PATCH v4 00/12] Add VIRTIO sound card Emmanouil Pitsidianakis
2023-07-20 12:57 ` [PATCH v4 01/12] Add virtio-sound device stub Emmanouil Pitsidianakis
2023-07-25 14:22 ` Marc-André Lureau
2023-07-25 14:31 ` Marc-André Lureau
2023-07-25 14:50 ` Michael S. Tsirkin
2023-07-20 12:57 ` [PATCH v4 02/12] Add virtio-sound-pci device Emmanouil Pitsidianakis
2023-07-20 12:57 ` [PATCH v4 03/12] virtio-sound: handle control messages and streams Emmanouil Pitsidianakis
2023-07-20 12:57 ` [PATCH v4 04/12] virtio-sound: set PCM stream parameters Emmanouil Pitsidianakis
2023-07-20 12:57 ` [PATCH v4 05/12] virtio-sound: prepare PCM streams Emmanouil Pitsidianakis
2023-07-25 13:38 ` Marc-André Lureau
2023-07-20 12:57 ` [PATCH v4 06/12] virtio-sound: handle VIRTIO_SND_R_PCM_INFO request Emmanouil Pitsidianakis
2023-07-25 14:29 ` Marc-André Lureau
2023-07-25 14:46 ` Michael S. Tsirkin
2023-07-25 14:54 ` Marc-André Lureau
2023-07-25 16:15 ` Michael S. Tsirkin
2023-07-25 14:30 ` Marc-André Lureau
2023-07-20 12:57 ` [PATCH v4 07/12] virtio-sound: handle VIRTIO_SND_R_PCM_{START,STOP} Emmanouil Pitsidianakis
2023-07-20 12:57 ` [PATCH v4 08/12] virtio-sound: handle VIRTIO_SND_PCM_SET_PARAMS Emmanouil Pitsidianakis
2023-07-20 12:57 ` [PATCH v4 09/12] virtio-sound: handle VIRTIO_SND_R_PCM_PREPARE Emmanouil Pitsidianakis
2023-07-20 12:57 ` [PATCH v4 10/12] virtio-sound: handle VIRTIO_SND_PCM_RELEASE Emmanouil Pitsidianakis
2023-07-20 12:57 ` [PATCH v4 11/12] virtio-sound: implement audio output (TX) Emmanouil Pitsidianakis
2023-07-20 12:57 ` [PATCH v4 12/12] virtio-sound: implement audio capture (RX) Emmanouil Pitsidianakis
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).