From: Emmanouil Pitsidianakis <manos.pitsidiana...@linaro.org> 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.
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> Reviewed-by: Alex Bennée <alex.ben...@linaro.org> --- hw/virtio/trace-events | 1 + hw/virtio/virtio-snd.c | 49 ++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 48 insertions(+), 2 deletions(-) diff --git a/hw/virtio/trace-events b/hw/virtio/trace-events index 88de2021c8..7044b110b7 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 ec945d55a7..50b5a9d5df 100644 --- a/hw/virtio/virtio-snd.c +++ b/hw/virtio/virtio-snd.c @@ -426,29 +426,70 @@ static uint32_t virtio_snd_pcm_prepare(VirtIOSound *s, uint32_t stream_id) 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 }; +/* + * 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; + uint32_t stream_id; + size_t msg_sz = iov_to_buf(cmd->elem->out_sg, + cmd->elem->out_num, + 0, + &req, + sizeof(virtio_snd_pcm_hdr)); + + if (msg_sz != sizeof(virtio_snd_pcm_hdr)) { + qemu_log_mask(LOG_GUEST_ERROR, + "%s: virtio-snd command size incorrect %zu vs \ + %zu\n", __func__, msg_sz, sizeof(virtio_snd_pcm_hdr)); + cmd->resp.code = cpu_to_le32(VIRTIO_SND_S_BAD_MSG); + return; + } + + stream_id = le32_to_cpu(req.stream_id); + cmd->resp.code = cpu_to_le32(VIRTIO_SND_S_OK); + trace_virtio_snd_handle_pcm_start_stop(start ? "VIRTIO_SND_R_PCM_START" : + "VIRTIO_SND_R_PCM_STOP", stream_id); + stream = virtio_snd_pcm_get_stream(s, stream_id); + if (stream == NULL) { + error_report("Invalid stream id: %"PRIu32, req.stream_id); + cmd->resp.code = cpu_to_le32(VIRTIO_SND_S_BAD_MSG); + return; + } + stream->active = start; +} + /* * The actual processing done in virtio_snd_process_cmdq(). * * @s: VirtIOSound device * @cmd: control command request */ @@ -456,66 +497,70 @@ static inline void process_cmd(VirtIOSound *s, virtio_snd_ctrl_command *cmd) { uint32_t code; size_t msg_sz = iov_to_buf(cmd->elem->out_sg, cmd->elem->out_num, 0, &cmd->ctrl, sizeof(virtio_snd_hdr)); if (msg_sz != sizeof(virtio_snd_hdr)) { /* * TODO: do we need to set DEVICE_NEEDS_RESET? */ qemu_log_mask(LOG_GUEST_ERROR, "%s: virtio-snd command size incorrect %zu vs \ %zu\n", __func__, msg_sz, sizeof(virtio_snd_hdr)); return; } code = le32_to_cpu(cmd->ctrl.code); trace_virtio_snd_handle_code(code, print_code(code)); switch (code) { case VIRTIO_SND_R_JACK_INFO: case VIRTIO_SND_R_JACK_REMAP: qemu_log_mask(LOG_UNIMP, "virtio_snd: jack functionality is unimplemented.\n"); cmd->resp.code = cpu_to_le32(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: + 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 = cpu_to_le32(VIRTIO_SND_S_NOT_SUPP); break; case VIRTIO_SND_R_CHMAP_INFO: qemu_log_mask(LOG_UNIMP, "virtio_snd: chmap info functionality is unimplemented.\n"); trace_virtio_snd_handle_chmap_info(); cmd->resp.code = cpu_to_le32(VIRTIO_SND_S_NOT_SUPP); break; default: /* error */ error_report("virtio snd header not recognized: %"PRIu32, code); cmd->resp.code = cpu_to_le32(VIRTIO_SND_S_BAD_MSG); } iov_from_buf(cmd->elem->in_sg, cmd->elem->in_num, 0, &cmd->resp, sizeof(virtio_snd_hdr)); virtqueue_push(cmd->vq, cmd->elem, sizeof(virtio_snd_hdr)); virtio_notify(VIRTIO_DEVICE(s), cmd->vq); } /* * Consume all elements in command queue. * * @s: VirtIOSound device */ -- 2.39.2