Le 11/02/2022 à 23:13, Shreyansh Chouhan a écrit :
Signed-off-by: Shreyansh Chouhan <chouhan.shreyansh2...@gmail.com>
---
hw/audio/virtio-snd.c | 81 +++++++++++++++++++++++++++++++++++++++++--
1 file changed, 79 insertions(+), 2 deletions(-)
diff --git a/hw/audio/virtio-snd.c b/hw/audio/virtio-snd.c
index a87922f91b..c2af26f3cb 100644
--- a/hw/audio/virtio-snd.c
+++ b/hw/audio/virtio-snd.c
@@ -92,6 +92,80 @@ static uint64_t virtio_snd_get_features(VirtIODevice *vdev,
uint64_t features,
{
return vdev->host_features;
}
+/*
+ * Get a specific jack from the VirtIOSound card.
+ *
+ * @s: VirtIOSound card device.
+ * @id: Jack id
+ */
+static virtio_snd_jack *virtio_snd_get_jack(VirtIOSound *s, uint32_t id)
+{
+ if (id >= s->snd_conf.jacks) {
+ return NULL;
+ }
+ return s->jacks[id];
+}
+
+/*
+ * Handles VIRTIO_SND_R_JACK_INFO.
+ * The function writes the info structs and response to the virtqueue element.
+ * Returns the used size in bytes.
+ *
+ * @s: VirtIOSound card
+ * @elem: The request element from control queue
+ */
+static uint32_t virtio_snd_handle_jack_info(VirtIOSound *s,
+ VirtQueueElement *elem)
+{
+ virtio_snd_query_info req;
+ size_t sz = iov_to_buf(elem->out_sg, elem->out_num, 0, &req, sizeof(req));
+ assert(sz == sizeof(virtio_snd_query_info));
+
+ virtio_snd_hdr resp;
+
+ if (iov_size(elem->in_sg, elem->in_num) <
+ sizeof(virtio_snd_hdr) + req.count * req.size) {
+ virtio_snd_err("jack info: buffer too small got: %lu needed: %lu\n",
+ iov_size(elem->in_sg, elem->in_num),
+ sizeof(virtio_snd_hdr) + req.count * req.size);
+ resp.code = VIRTIO_SND_S_BAD_MSG;
+ goto done;
+ }
+
+ virtio_snd_jack_info *jack_info = g_new0(virtio_snd_jack_info, req.count);
+ for (int i = req.start_id; i < req.count + req.start_id; i++) {
+ virtio_snd_jack *jack = virtio_snd_get_jack(s, i);
+ if (!jack) {
+ virtio_snd_err("Invalid jack id: %d\n", i);
+ resp.code = VIRTIO_SND_S_BAD_MSG;
+ goto done;
+ }
+
+ jack_info[i - req.start_id].hdr.hda_fn_nid = jack->hda_fn_nid;
+ jack_info[i - req.start_id].features = jack->features;
+ jack_info[i - req.start_id].hda_reg_defconf = jack->hda_reg_defconf;
+ jack_info[i - req.start_id].hda_reg_caps = jack->hda_reg_caps;
+ jack_info[i - req.start_id].connected = jack->connected;
+ memset(jack_info[i - req.start_id].padding, 0,
+ sizeof(jack_info[i - req.start_id].padding));
+ }
+
+ resp.code = VIRTIO_SND_S_OK;
+done:
+ sz = iov_from_buf(elem->in_sg, elem->in_num, 0, &resp, sizeof(resp));
+ assert(sz == sizeof(virtio_snd_hdr));
+
+ if (resp.code == VIRTIO_SND_S_BAD_MSG) {
+ g_free(jack_info);
+ return sz;
+ }
+
+ sz = iov_from_buf(elem->in_sg, elem->in_num, sizeof(virtio_snd_hdr),
+ jack_info, sizeof(virtio_snd_jack_info) * req.count);
+ assert(sz == req.count * req.size);
+ g_free(jack_info);
+ return sizeof(virtio_snd_hdr) + sz;
+}
/* The control queue handler. Pops an element from the control virtqueue,
* checks the header and performs the requested action. Finally marks the
@@ -102,6 +176,7 @@ static uint64_t virtio_snd_get_features(VirtIODevice *vdev,
uint64_t features,
*/
static void virtio_snd_handle_ctrl(VirtIODevice *vdev, VirtQueue *vq)
{
+ VirtIOSound *s = VIRTIO_SOUND(vdev);
virtio_snd_hdr ctrl;
VirtQueueElement *elem = NULL;
@@ -131,7 +206,8 @@ static void virtio_snd_handle_ctrl(VirtIODevice *vdev,
VirtQueue *vq)
/* error */
virtio_snd_err("virtio snd ctrl could not read header\n");
} else if (ctrl.code == VIRTIO_SND_R_JACK_INFO) {
- virtio_snd_log("VIRTIO_SND_R_JACK_INFO");
+ sz = virtio_snd_handle_jack_info(s, elem);
+ goto done;
} else if (ctrl.code == VIRTIO_SND_R_JACK_REMAP) {
virtio_snd_log("VIRTIO_SND_R_JACK_REMAP");
} else if (ctrl.code == VIRTIO_SND_R_PCM_INFO) {
@@ -156,8 +232,9 @@ static void virtio_snd_handle_ctrl(VirtIODevice *vdev,
VirtQueue *vq)
virtio_snd_hdr resp;
resp.code = VIRTIO_SND_S_OK;
sz = iov_from_buf(elem->in_sg, elem->in_num, 0, &resp, sizeof(resp));
- virtqueue_push(vq, elem, sz);
+done:
+ virtqueue_push(vq, elem, sz);
virtio_notify(vdev, vq);
g_free(iov2);
g_free(elem);
This patch has a warning:
.../hw/audio/virtio-snd.c: In function 'virtio_snd_handle_ctrl':
.../include/qemu/iov.h:49:16: error: 'jack_info' may be used uninitialized in this function
[-Werror=maybe-uninitialized]
49 | return iov_from_buf_full(iov, iov_cnt, offset, buf, bytes);
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
...hw/audio/virtio-snd.c:135:27: note: 'jack_info' was declared here
135 | virtio_snd_jack_info *jack_info = g_new0(virtio_snd_jack_info,
req.count);
| ^~~~~~~~~
Thanks,
Laurent