On 28/8/23 21:55, Emmanouil Pitsidianakis wrote:
Respond to the VIRTIO_SND_R_PCM_INFO control request with the parameters
of each requested PCM stream.
Based-on:
https://github.com/OpenSynergy/qemu/commit/5a2f350eec5d157b90d9c7b40a8e603f4da92471
Signed-off-by: Igor Skalkin <igor.skal...@opensynergy.com>
Signed-off-by: Anton Yakovlev <anton.yakov...@opensynergy.com>
Signed-off-by: Emmanouil Pitsidianakis <manos.pitsidiana...@linaro.org>
---
hw/virtio/trace-events | 1 +
hw/virtio/virtio-snd.c | 76 ++++++++++++++++++++++++++++++++++++++++++
2 files changed, 77 insertions(+)
+/*
+ * 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: %zu, needed: %zu",
+ 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++) {
Starting from req.start_id seems to increase this code complexity.
+ 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;
+ }
+
+ 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);
+}