1 /*
2 * VIRTIO Sound Device conforming to
3 *
4 * "Virtual I/O Device (VIRTIO) Version 1.2
5 * Committee Specification Draft 01
6 * 09 May 2022"
7 *
8 * <https://docs.oasis-open.org/virtio/virtio/v1.2/csd01/virtio-v1.2-csd01.html#x1-52900014>
9 *
10 * Copyright (c) 2023 Emmanouil Pitsidianakis <manos.pitsidianakis@linaro.org>
11 * Copyright (C) 2019 OpenSynergy GmbH
12 *
13 * This work is licensed under the terms of the GNU GPL, version 2 or
14 * (at your option) any later version. See the COPYING file in the
15 * top-level directory.
16 */
17
18 #include "qemu/osdep.h"
19 #include "qemu/iov.h"
20 #include "qemu/log.h"
21 #include "qemu/error-report.h"
22 #include "qemu/lockable.h"
23 #include "system/runstate.h"
24 #include "trace.h"
25 #include "qapi/error.h"
26 #include "hw/audio/virtio-snd.h"
27
28 #define VIRTIO_SOUND_VM_VERSION 1
29 #define VIRTIO_SOUND_JACK_DEFAULT 0
30 #define VIRTIO_SOUND_STREAM_DEFAULT 2
31 #define VIRTIO_SOUND_CHMAP_DEFAULT 0
32 #define VIRTIO_SOUND_HDA_FN_NID 0
33
34 static void virtio_snd_pcm_out_cb(void *data, int available);
35 static void virtio_snd_process_cmdq(VirtIOSound *s);
36 static void virtio_snd_pcm_flush(VirtIOSoundPCMStream *stream);
37 static void virtio_snd_pcm_in_cb(void *data, int available);
38 static void virtio_snd_unrealize(DeviceState *dev);
39
40 static uint32_t supported_formats = BIT(VIRTIO_SND_PCM_FMT_S8)
41 | BIT(VIRTIO_SND_PCM_FMT_U8)
42 | BIT(VIRTIO_SND_PCM_FMT_S16)
43 | BIT(VIRTIO_SND_PCM_FMT_U16)
44 | BIT(VIRTIO_SND_PCM_FMT_S32)
45 | BIT(VIRTIO_SND_PCM_FMT_U32)
46 | BIT(VIRTIO_SND_PCM_FMT_FLOAT);
47
48 static uint32_t supported_rates = BIT(VIRTIO_SND_PCM_RATE_5512)
49 | BIT(VIRTIO_SND_PCM_RATE_8000)
50 | BIT(VIRTIO_SND_PCM_RATE_11025)
51 | BIT(VIRTIO_SND_PCM_RATE_16000)
52 | BIT(VIRTIO_SND_PCM_RATE_22050)
53 | BIT(VIRTIO_SND_PCM_RATE_32000)
54 | BIT(VIRTIO_SND_PCM_RATE_44100)
55 | BIT(VIRTIO_SND_PCM_RATE_48000)
56 | BIT(VIRTIO_SND_PCM_RATE_64000)
57 | BIT(VIRTIO_SND_PCM_RATE_88200)
58 | BIT(VIRTIO_SND_PCM_RATE_96000)
59 | BIT(VIRTIO_SND_PCM_RATE_176400)
60 | BIT(VIRTIO_SND_PCM_RATE_192000)
61 | BIT(VIRTIO_SND_PCM_RATE_384000);
62
63 static const VMStateDescription vmstate_virtio_snd_device = {
64 .name = TYPE_VIRTIO_SND,
65 .version_id = VIRTIO_SOUND_VM_VERSION,
66 .minimum_version_id = VIRTIO_SOUND_VM_VERSION,
67 };
68
69 static const VMStateDescription vmstate_virtio_snd = {
70 .name = TYPE_VIRTIO_SND,
71 .unmigratable = 1,
72 .minimum_version_id = VIRTIO_SOUND_VM_VERSION,
73 .version_id = VIRTIO_SOUND_VM_VERSION,
74 .fields = (const VMStateField[]) {
75 VMSTATE_VIRTIO_DEVICE,
76 VMSTATE_END_OF_LIST()
77 },
78 };
79
80 static const Property virtio_snd_properties[] = {
81 DEFINE_AUDIO_PROPERTIES(VirtIOSound, card),
82 DEFINE_PROP_UINT32("jacks", VirtIOSound, snd_conf.jacks,
83 VIRTIO_SOUND_JACK_DEFAULT),
84 DEFINE_PROP_UINT32("streams", VirtIOSound, snd_conf.streams,
85 VIRTIO_SOUND_STREAM_DEFAULT),
86 DEFINE_PROP_UINT32("chmaps", VirtIOSound, snd_conf.chmaps,
87 VIRTIO_SOUND_CHMAP_DEFAULT),
88 };
89
90 static void
virtio_snd_get_config(VirtIODevice * vdev,uint8_t * config)91 virtio_snd_get_config(VirtIODevice *vdev, uint8_t *config)
92 {
93 VirtIOSound *s = VIRTIO_SND(vdev);
94 virtio_snd_config *sndconfig =
95 (virtio_snd_config *)config;
96 trace_virtio_snd_get_config(vdev,
97 s->snd_conf.jacks,
98 s->snd_conf.streams,
99 s->snd_conf.chmaps);
100
101 memcpy(sndconfig, &s->snd_conf, sizeof(s->snd_conf));
102 cpu_to_le32s(&sndconfig->jacks);
103 cpu_to_le32s(&sndconfig->streams);
104 cpu_to_le32s(&sndconfig->chmaps);
105
106 }
107
108 static void
virtio_snd_pcm_buffer_free(VirtIOSoundPCMBuffer * buffer)109 virtio_snd_pcm_buffer_free(VirtIOSoundPCMBuffer *buffer)
110 {
111 g_free(buffer->elem);
112 g_free(buffer);
113 }
114
115 static void
virtio_snd_ctrl_cmd_free(virtio_snd_ctrl_command * cmd)116 virtio_snd_ctrl_cmd_free(virtio_snd_ctrl_command *cmd)
117 {
118 g_free(cmd->elem);
119 g_free(cmd);
120 }
121
122 /*
123 * Get a specific stream from the virtio sound card device.
124 * Returns NULL if @stream_id is invalid or not allocated.
125 *
126 * @s: VirtIOSound device
127 * @stream_id: stream id
128 */
virtio_snd_pcm_get_stream(VirtIOSound * s,uint32_t stream_id)129 static VirtIOSoundPCMStream *virtio_snd_pcm_get_stream(VirtIOSound *s,
130 uint32_t stream_id)
131 {
132 return stream_id >= s->snd_conf.streams ? NULL :
133 s->pcm->streams[stream_id];
134 }
135
136 /*
137 * Get params for a specific stream.
138 *
139 * @s: VirtIOSound device
140 * @stream_id: stream id
141 */
virtio_snd_pcm_get_params(VirtIOSound * s,uint32_t stream_id)142 static virtio_snd_pcm_set_params *virtio_snd_pcm_get_params(VirtIOSound *s,
143 uint32_t stream_id)
144 {
145 return stream_id >= s->snd_conf.streams ? NULL
146 : &s->pcm->pcm_params[stream_id];
147 }
148
149 /*
150 * Handle the VIRTIO_SND_R_PCM_INFO request.
151 * The function writes the info structs to the request element.
152 *
153 * @s: VirtIOSound device
154 * @cmd: The request command queue element from VirtIOSound cmdq field
155 */
virtio_snd_handle_pcm_info(VirtIOSound * s,virtio_snd_ctrl_command * cmd)156 static void virtio_snd_handle_pcm_info(VirtIOSound *s,
157 virtio_snd_ctrl_command *cmd)
158 {
159 uint32_t stream_id, start_id, count, size;
160 virtio_snd_pcm_info val;
161 virtio_snd_query_info req;
162 VirtIOSoundPCMStream *stream = NULL;
163 g_autofree virtio_snd_pcm_info *pcm_info = NULL;
164 size_t msg_sz = iov_to_buf(cmd->elem->out_sg,
165 cmd->elem->out_num,
166 0,
167 &req,
168 sizeof(virtio_snd_query_info));
169
170 if (msg_sz != sizeof(virtio_snd_query_info)) {
171 /*
172 * TODO: do we need to set DEVICE_NEEDS_RESET?
173 */
174 qemu_log_mask(LOG_GUEST_ERROR,
175 "%s: virtio-snd command size incorrect %zu vs \
176 %zu\n", __func__, msg_sz, sizeof(virtio_snd_query_info));
177 cmd->resp.code = cpu_to_le32(VIRTIO_SND_S_BAD_MSG);
178 return;
179 }
180
181 start_id = le32_to_cpu(req.start_id);
182 count = le32_to_cpu(req.count);
183 size = le32_to_cpu(req.size);
184
185 if (iov_size(cmd->elem->in_sg, cmd->elem->in_num) <
186 sizeof(virtio_snd_hdr) + size * count) {
187 /*
188 * TODO: do we need to set DEVICE_NEEDS_RESET?
189 */
190 error_report("pcm info: buffer too small, got: %zu, needed: %zu",
191 iov_size(cmd->elem->in_sg, cmd->elem->in_num),
192 sizeof(virtio_snd_pcm_info));
193 cmd->resp.code = cpu_to_le32(VIRTIO_SND_S_BAD_MSG);
194 return;
195 }
196
197 pcm_info = g_new0(virtio_snd_pcm_info, count);
198 for (uint32_t i = 0; i < count; i++) {
199 stream_id = i + start_id;
200 trace_virtio_snd_handle_pcm_info(stream_id);
201 stream = virtio_snd_pcm_get_stream(s, stream_id);
202 if (!stream) {
203 error_report("Invalid stream id: %"PRIu32, stream_id);
204 cmd->resp.code = cpu_to_le32(VIRTIO_SND_S_BAD_MSG);
205 return;
206 }
207 val = stream->info;
208 val.hdr.hda_fn_nid = cpu_to_le32(val.hdr.hda_fn_nid);
209 val.features = cpu_to_le32(val.features);
210 val.formats = cpu_to_le64(val.formats);
211 val.rates = cpu_to_le64(val.rates);
212 /*
213 * 5.14.6.6.2.1 Device Requirements: Stream Information The device MUST
214 * NOT set undefined feature, format, rate and direction values. The
215 * device MUST initialize the padding bytes to 0.
216 */
217 pcm_info[i] = val;
218 memset(&pcm_info[i].padding, 0, 5);
219 }
220
221 cmd->payload_size = sizeof(virtio_snd_pcm_info) * count;
222 cmd->resp.code = cpu_to_le32(VIRTIO_SND_S_OK);
223 iov_from_buf(cmd->elem->in_sg,
224 cmd->elem->in_num,
225 sizeof(virtio_snd_hdr),
226 pcm_info,
227 cmd->payload_size);
228 }
229
230 /*
231 * Set the given stream params.
232 * Called by both virtio_snd_handle_pcm_set_params and during device
233 * initialization.
234 * Returns the response status code. (VIRTIO_SND_S_*).
235 *
236 * @s: VirtIOSound device
237 * @params: The PCM params as defined in the virtio specification
238 */
239 static
virtio_snd_set_pcm_params(VirtIOSound * s,uint32_t stream_id,virtio_snd_pcm_set_params * params)240 uint32_t virtio_snd_set_pcm_params(VirtIOSound *s,
241 uint32_t stream_id,
242 virtio_snd_pcm_set_params *params)
243 {
244 virtio_snd_pcm_set_params *st_params;
245
246 if (stream_id >= s->snd_conf.streams || s->pcm->pcm_params == NULL) {
247 /*
248 * TODO: do we need to set DEVICE_NEEDS_RESET?
249 */
250 virtio_error(VIRTIO_DEVICE(s), "Streams have not been initialized.\n");
251 return cpu_to_le32(VIRTIO_SND_S_BAD_MSG);
252 }
253
254 st_params = virtio_snd_pcm_get_params(s, stream_id);
255
256 if (params->channels < 1 || params->channels > AUDIO_MAX_CHANNELS) {
257 error_report("Number of channels is not supported.");
258 return cpu_to_le32(VIRTIO_SND_S_NOT_SUPP);
259 }
260 if (params->format >= sizeof(supported_formats) * BITS_PER_BYTE ||
261 !(supported_formats & BIT(params->format))) {
262 error_report("Stream format is not supported.");
263 return cpu_to_le32(VIRTIO_SND_S_NOT_SUPP);
264 }
265 if (params->rate >= sizeof(supported_rates) * BITS_PER_BYTE ||
266 !(supported_rates & BIT(params->rate))) {
267 error_report("Stream rate is not supported.");
268 return cpu_to_le32(VIRTIO_SND_S_NOT_SUPP);
269 }
270
271 st_params->buffer_bytes = le32_to_cpu(params->buffer_bytes);
272 st_params->period_bytes = le32_to_cpu(params->period_bytes);
273 st_params->features = le32_to_cpu(params->features);
274 /* the following are uint8_t, so there's no need to bswap the values. */
275 st_params->channels = params->channels;
276 st_params->format = params->format;
277 st_params->rate = params->rate;
278
279 return cpu_to_le32(VIRTIO_SND_S_OK);
280 }
281
282 /*
283 * Handles the VIRTIO_SND_R_PCM_SET_PARAMS request.
284 *
285 * @s: VirtIOSound device
286 * @cmd: The request command queue element from VirtIOSound cmdq field
287 */
virtio_snd_handle_pcm_set_params(VirtIOSound * s,virtio_snd_ctrl_command * cmd)288 static void virtio_snd_handle_pcm_set_params(VirtIOSound *s,
289 virtio_snd_ctrl_command *cmd)
290 {
291 virtio_snd_pcm_set_params req = { 0 };
292 uint32_t stream_id;
293 size_t msg_sz = iov_to_buf(cmd->elem->out_sg,
294 cmd->elem->out_num,
295 0,
296 &req,
297 sizeof(virtio_snd_pcm_set_params));
298
299 if (msg_sz != sizeof(virtio_snd_pcm_set_params)) {
300 /*
301 * TODO: do we need to set DEVICE_NEEDS_RESET?
302 */
303 qemu_log_mask(LOG_GUEST_ERROR,
304 "%s: virtio-snd command size incorrect %zu vs \
305 %zu\n", __func__, msg_sz, sizeof(virtio_snd_pcm_set_params));
306 cmd->resp.code = cpu_to_le32(VIRTIO_SND_S_BAD_MSG);
307 return;
308 }
309 stream_id = le32_to_cpu(req.hdr.stream_id);
310 trace_virtio_snd_handle_pcm_set_params(stream_id);
311 cmd->resp.code = virtio_snd_set_pcm_params(s, stream_id, &req);
312 }
313
314 /*
315 * Get a QEMU Audiosystem compatible format value from a VIRTIO_SND_PCM_FMT_*
316 */
virtio_snd_get_qemu_format(uint32_t format)317 static AudioFormat virtio_snd_get_qemu_format(uint32_t format)
318 {
319 #define CASE(FMT) \
320 case VIRTIO_SND_PCM_FMT_##FMT: \
321 return AUDIO_FORMAT_##FMT;
322
323 switch (format) {
324 CASE(U8)
325 CASE(S8)
326 CASE(U16)
327 CASE(S16)
328 CASE(U32)
329 CASE(S32)
330 case VIRTIO_SND_PCM_FMT_FLOAT:
331 return AUDIO_FORMAT_F32;
332 default:
333 g_assert_not_reached();
334 }
335
336 #undef CASE
337 }
338
339 /*
340 * Get a QEMU Audiosystem compatible frequency value from a
341 * VIRTIO_SND_PCM_RATE_*
342 */
virtio_snd_get_qemu_freq(uint32_t rate)343 static uint32_t virtio_snd_get_qemu_freq(uint32_t rate)
344 {
345 #define CASE(RATE) \
346 case VIRTIO_SND_PCM_RATE_##RATE: \
347 return RATE;
348
349 switch (rate) {
350 CASE(5512)
351 CASE(8000)
352 CASE(11025)
353 CASE(16000)
354 CASE(22050)
355 CASE(32000)
356 CASE(44100)
357 CASE(48000)
358 CASE(64000)
359 CASE(88200)
360 CASE(96000)
361 CASE(176400)
362 CASE(192000)
363 CASE(384000)
364 default:
365 g_assert_not_reached();
366 }
367
368 #undef CASE
369 }
370
371 /*
372 * Get QEMU Audiosystem compatible audsettings from virtio based pcm stream
373 * params.
374 */
virtio_snd_get_qemu_audsettings(audsettings * as,virtio_snd_pcm_set_params * params)375 static void virtio_snd_get_qemu_audsettings(audsettings *as,
376 virtio_snd_pcm_set_params *params)
377 {
378 as->nchannels = MIN(AUDIO_MAX_CHANNELS, params->channels);
379 as->fmt = virtio_snd_get_qemu_format(params->format);
380 as->freq = virtio_snd_get_qemu_freq(params->rate);
381 as->endianness = 0; /* Conforming to VIRTIO 1.0: always little endian. */
382 }
383
384 /*
385 * Close a stream and free all its resources.
386 *
387 * @stream: VirtIOSoundPCMStream *stream
388 */
virtio_snd_pcm_close(VirtIOSoundPCMStream * stream)389 static void virtio_snd_pcm_close(VirtIOSoundPCMStream *stream)
390 {
391 if (stream) {
392 virtio_snd_pcm_flush(stream);
393 if (stream->info.direction == VIRTIO_SND_D_OUTPUT) {
394 AUD_close_out(&stream->pcm->snd->card, stream->voice.out);
395 stream->voice.out = NULL;
396 } else if (stream->info.direction == VIRTIO_SND_D_INPUT) {
397 AUD_close_in(&stream->pcm->snd->card, stream->voice.in);
398 stream->voice.in = NULL;
399 }
400 }
401 }
402
403 /*
404 * Prepares a VirtIOSound card stream.
405 * Returns the response status code. (VIRTIO_SND_S_*).
406 *
407 * @s: VirtIOSound device
408 * @stream_id: stream id
409 */
virtio_snd_pcm_prepare(VirtIOSound * s,uint32_t stream_id)410 static uint32_t virtio_snd_pcm_prepare(VirtIOSound *s, uint32_t stream_id)
411 {
412 audsettings as;
413 virtio_snd_pcm_set_params *params;
414 VirtIOSoundPCMStream *stream;
415
416 if (s->pcm->streams == NULL ||
417 s->pcm->pcm_params == NULL ||
418 stream_id >= s->snd_conf.streams) {
419 return cpu_to_le32(VIRTIO_SND_S_BAD_MSG);
420 }
421
422 params = virtio_snd_pcm_get_params(s, stream_id);
423 if (params == NULL) {
424 return cpu_to_le32(VIRTIO_SND_S_BAD_MSG);
425 }
426
427 stream = virtio_snd_pcm_get_stream(s, stream_id);
428 if (stream == NULL) {
429 stream = g_new0(VirtIOSoundPCMStream, 1);
430 stream->active = false;
431 stream->id = stream_id;
432 stream->pcm = s->pcm;
433 stream->s = s;
434 qemu_mutex_init(&stream->queue_mutex);
435 QSIMPLEQ_INIT(&stream->queue);
436
437 /*
438 * stream_id >= s->snd_conf.streams was checked before so this is
439 * in-bounds
440 */
441 s->pcm->streams[stream_id] = stream;
442 }
443
444 virtio_snd_get_qemu_audsettings(&as, params);
445 stream->info.direction = stream_id < s->snd_conf.streams / 2 +
446 (s->snd_conf.streams & 1) ? VIRTIO_SND_D_OUTPUT : VIRTIO_SND_D_INPUT;
447 stream->info.hdr.hda_fn_nid = VIRTIO_SOUND_HDA_FN_NID;
448 stream->info.features = 0;
449 stream->info.channels_min = 1;
450 stream->info.channels_max = as.nchannels;
451 stream->info.formats = supported_formats;
452 stream->info.rates = supported_rates;
453 stream->params = *params;
454
455 stream->positions[0] = VIRTIO_SND_CHMAP_FL;
456 stream->positions[1] = VIRTIO_SND_CHMAP_FR;
457 stream->as = as;
458
459 if (stream->info.direction == VIRTIO_SND_D_OUTPUT) {
460 stream->voice.out = AUD_open_out(&s->card,
461 stream->voice.out,
462 "virtio-sound.out",
463 stream,
464 virtio_snd_pcm_out_cb,
465 &as);
466 AUD_set_volume_out(stream->voice.out, 0, 255, 255);
467 } else {
468 stream->voice.in = AUD_open_in(&s->card,
469 stream->voice.in,
470 "virtio-sound.in",
471 stream,
472 virtio_snd_pcm_in_cb,
473 &as);
474 AUD_set_volume_in(stream->voice.in, 0, 255, 255);
475 }
476
477 return cpu_to_le32(VIRTIO_SND_S_OK);
478 }
479
print_code(uint32_t code)480 static const char *print_code(uint32_t code)
481 {
482 #define CASE(CODE) \
483 case VIRTIO_SND_R_##CODE: \
484 return "VIRTIO_SND_R_"#CODE
485
486 switch (code) {
487 CASE(JACK_INFO);
488 CASE(JACK_REMAP);
489 CASE(PCM_INFO);
490 CASE(PCM_SET_PARAMS);
491 CASE(PCM_PREPARE);
492 CASE(PCM_RELEASE);
493 CASE(PCM_START);
494 CASE(PCM_STOP);
495 CASE(CHMAP_INFO);
496 default:
497 return "invalid code";
498 }
499
500 #undef CASE
501 };
502
503 /*
504 * Handles VIRTIO_SND_R_PCM_PREPARE.
505 *
506 * @s: VirtIOSound device
507 * @cmd: The request command queue element from VirtIOSound cmdq field
508 */
virtio_snd_handle_pcm_prepare(VirtIOSound * s,virtio_snd_ctrl_command * cmd)509 static void virtio_snd_handle_pcm_prepare(VirtIOSound *s,
510 virtio_snd_ctrl_command *cmd)
511 {
512 uint32_t stream_id;
513 size_t msg_sz = iov_to_buf(cmd->elem->out_sg,
514 cmd->elem->out_num,
515 sizeof(virtio_snd_hdr),
516 &stream_id,
517 sizeof(stream_id));
518
519 stream_id = le32_to_cpu(stream_id);
520 cmd->resp.code = msg_sz == sizeof(stream_id)
521 ? virtio_snd_pcm_prepare(s, stream_id)
522 : cpu_to_le32(VIRTIO_SND_S_BAD_MSG);
523 }
524
525 /*
526 * Handles VIRTIO_SND_R_PCM_START.
527 *
528 * @s: VirtIOSound device
529 * @cmd: The request command queue element from VirtIOSound cmdq field
530 * @start: whether to start or stop the device
531 */
virtio_snd_handle_pcm_start_stop(VirtIOSound * s,virtio_snd_ctrl_command * cmd,bool start)532 static void virtio_snd_handle_pcm_start_stop(VirtIOSound *s,
533 virtio_snd_ctrl_command *cmd,
534 bool start)
535 {
536 VirtIOSoundPCMStream *stream;
537 virtio_snd_pcm_hdr req;
538 uint32_t stream_id;
539 size_t msg_sz = iov_to_buf(cmd->elem->out_sg,
540 cmd->elem->out_num,
541 0,
542 &req,
543 sizeof(virtio_snd_pcm_hdr));
544
545 if (msg_sz != sizeof(virtio_snd_pcm_hdr)) {
546 qemu_log_mask(LOG_GUEST_ERROR,
547 "%s: virtio-snd command size incorrect %zu vs \
548 %zu\n", __func__, msg_sz, sizeof(virtio_snd_pcm_hdr));
549 cmd->resp.code = cpu_to_le32(VIRTIO_SND_S_BAD_MSG);
550 return;
551 }
552
553 stream_id = le32_to_cpu(req.stream_id);
554 cmd->resp.code = cpu_to_le32(VIRTIO_SND_S_OK);
555 trace_virtio_snd_handle_pcm_start_stop(start ? "VIRTIO_SND_R_PCM_START" :
556 "VIRTIO_SND_R_PCM_STOP", stream_id);
557
558 stream = virtio_snd_pcm_get_stream(s, stream_id);
559 if (stream) {
560 WITH_QEMU_LOCK_GUARD(&stream->queue_mutex) {
561 stream->active = start;
562 }
563 if (stream->info.direction == VIRTIO_SND_D_OUTPUT) {
564 AUD_set_active_out(stream->voice.out, start);
565 } else {
566 AUD_set_active_in(stream->voice.in, start);
567 }
568 } else {
569 error_report("Invalid stream id: %"PRIu32, stream_id);
570 cmd->resp.code = cpu_to_le32(VIRTIO_SND_S_BAD_MSG);
571 return;
572 }
573 stream->active = start;
574 }
575
576 /*
577 * Returns the number of I/O messages that are being processed.
578 *
579 * @stream: VirtIOSoundPCMStream
580 */
virtio_snd_pcm_get_io_msgs_count(VirtIOSoundPCMStream * stream)581 static size_t virtio_snd_pcm_get_io_msgs_count(VirtIOSoundPCMStream *stream)
582 {
583 VirtIOSoundPCMBuffer *buffer, *next;
584 size_t count = 0;
585
586 WITH_QEMU_LOCK_GUARD(&stream->queue_mutex) {
587 QSIMPLEQ_FOREACH_SAFE(buffer, &stream->queue, entry, next) {
588 count += 1;
589 }
590 }
591 return count;
592 }
593
594 /*
595 * Handles VIRTIO_SND_R_PCM_RELEASE.
596 *
597 * @s: VirtIOSound device
598 * @cmd: The request command queue element from VirtIOSound cmdq field
599 */
virtio_snd_handle_pcm_release(VirtIOSound * s,virtio_snd_ctrl_command * cmd)600 static void virtio_snd_handle_pcm_release(VirtIOSound *s,
601 virtio_snd_ctrl_command *cmd)
602 {
603 uint32_t stream_id;
604 VirtIOSoundPCMStream *stream;
605 size_t msg_sz = iov_to_buf(cmd->elem->out_sg,
606 cmd->elem->out_num,
607 sizeof(virtio_snd_hdr),
608 &stream_id,
609 sizeof(stream_id));
610
611 if (msg_sz != sizeof(stream_id)) {
612 /*
613 * TODO: do we need to set DEVICE_NEEDS_RESET?
614 */
615 qemu_log_mask(LOG_GUEST_ERROR,
616 "%s: virtio-snd command size incorrect %zu vs \
617 %zu\n", __func__, msg_sz, sizeof(stream_id));
618 cmd->resp.code = cpu_to_le32(VIRTIO_SND_S_BAD_MSG);
619 return;
620 }
621
622 stream_id = le32_to_cpu(stream_id);
623 trace_virtio_snd_handle_pcm_release(stream_id);
624 stream = virtio_snd_pcm_get_stream(s, stream_id);
625 if (stream == NULL) {
626 /*
627 * TODO: do we need to set DEVICE_NEEDS_RESET?
628 */
629 error_report("already released stream %"PRIu32, stream_id);
630 virtio_error(VIRTIO_DEVICE(s),
631 "already released stream %"PRIu32,
632 stream_id);
633 cmd->resp.code = cpu_to_le32(VIRTIO_SND_S_BAD_MSG);
634 return;
635 }
636
637 if (virtio_snd_pcm_get_io_msgs_count(stream)) {
638 /*
639 * virtio-v1.2-csd01, 5.14.6.6.5.1,
640 * Device Requirements: Stream Release
641 *
642 * - The device MUST complete all pending I/O messages for the
643 * specified stream ID.
644 * - The device MUST NOT complete the control request while there
645 * are pending I/O messages for the specified stream ID.
646 */
647 trace_virtio_snd_pcm_stream_flush(stream_id);
648 virtio_snd_pcm_flush(stream);
649 }
650
651 cmd->resp.code = cpu_to_le32(VIRTIO_SND_S_OK);
652 }
653
654 /*
655 * The actual processing done in virtio_snd_process_cmdq().
656 *
657 * @s: VirtIOSound device
658 * @cmd: control command request
659 */
660 static inline void
process_cmd(VirtIOSound * s,virtio_snd_ctrl_command * cmd)661 process_cmd(VirtIOSound *s, virtio_snd_ctrl_command *cmd)
662 {
663 uint32_t code;
664 size_t msg_sz = iov_to_buf(cmd->elem->out_sg,
665 cmd->elem->out_num,
666 0,
667 &cmd->ctrl,
668 sizeof(virtio_snd_hdr));
669
670 if (msg_sz != sizeof(virtio_snd_hdr)) {
671 /*
672 * TODO: do we need to set DEVICE_NEEDS_RESET?
673 */
674 qemu_log_mask(LOG_GUEST_ERROR,
675 "%s: virtio-snd command size incorrect %zu vs \
676 %zu\n", __func__, msg_sz, sizeof(virtio_snd_hdr));
677 return;
678 }
679
680 code = le32_to_cpu(cmd->ctrl.code);
681
682 trace_virtio_snd_handle_code(code, print_code(code));
683
684 switch (code) {
685 case VIRTIO_SND_R_JACK_INFO:
686 case VIRTIO_SND_R_JACK_REMAP:
687 qemu_log_mask(LOG_UNIMP,
688 "virtio_snd: jack functionality is unimplemented.\n");
689 cmd->resp.code = cpu_to_le32(VIRTIO_SND_S_NOT_SUPP);
690 break;
691 case VIRTIO_SND_R_PCM_INFO:
692 virtio_snd_handle_pcm_info(s, cmd);
693 break;
694 case VIRTIO_SND_R_PCM_START:
695 virtio_snd_handle_pcm_start_stop(s, cmd, true);
696 break;
697 case VIRTIO_SND_R_PCM_STOP:
698 virtio_snd_handle_pcm_start_stop(s, cmd, false);
699 break;
700 case VIRTIO_SND_R_PCM_SET_PARAMS:
701 virtio_snd_handle_pcm_set_params(s, cmd);
702 break;
703 case VIRTIO_SND_R_PCM_PREPARE:
704 virtio_snd_handle_pcm_prepare(s, cmd);
705 break;
706 case VIRTIO_SND_R_PCM_RELEASE:
707 virtio_snd_handle_pcm_release(s, cmd);
708 break;
709 case VIRTIO_SND_R_CHMAP_INFO:
710 qemu_log_mask(LOG_UNIMP,
711 "virtio_snd: chmap info functionality is unimplemented.\n");
712 trace_virtio_snd_handle_chmap_info();
713 cmd->resp.code = cpu_to_le32(VIRTIO_SND_S_NOT_SUPP);
714 break;
715 default:
716 /* error */
717 error_report("virtio snd header not recognized: %"PRIu32, code);
718 cmd->resp.code = cpu_to_le32(VIRTIO_SND_S_BAD_MSG);
719 }
720
721 iov_from_buf(cmd->elem->in_sg,
722 cmd->elem->in_num,
723 0,
724 &cmd->resp,
725 sizeof(virtio_snd_hdr));
726 virtqueue_push(cmd->vq, cmd->elem,
727 sizeof(virtio_snd_hdr) + cmd->payload_size);
728 virtio_notify(VIRTIO_DEVICE(s), cmd->vq);
729 }
730
731 /*
732 * Consume all elements in command queue.
733 *
734 * @s: VirtIOSound device
735 */
virtio_snd_process_cmdq(VirtIOSound * s)736 static void virtio_snd_process_cmdq(VirtIOSound *s)
737 {
738 virtio_snd_ctrl_command *cmd;
739
740 if (unlikely(qatomic_read(&s->processing_cmdq))) {
741 return;
742 }
743
744 WITH_QEMU_LOCK_GUARD(&s->cmdq_mutex) {
745 qatomic_set(&s->processing_cmdq, true);
746 while (!QTAILQ_EMPTY(&s->cmdq)) {
747 cmd = QTAILQ_FIRST(&s->cmdq);
748
749 /* process command */
750 process_cmd(s, cmd);
751
752 QTAILQ_REMOVE(&s->cmdq, cmd, next);
753
754 virtio_snd_ctrl_cmd_free(cmd);
755 }
756 qatomic_set(&s->processing_cmdq, false);
757 }
758 }
759
760 /*
761 * The control message handler. Pops an element from the control virtqueue,
762 * and stores them to VirtIOSound's cmdq queue and finally calls
763 * virtio_snd_process_cmdq() for processing.
764 *
765 * @vdev: VirtIOSound device
766 * @vq: Control virtqueue
767 */
virtio_snd_handle_ctrl(VirtIODevice * vdev,VirtQueue * vq)768 static void virtio_snd_handle_ctrl(VirtIODevice *vdev, VirtQueue *vq)
769 {
770 VirtIOSound *s = VIRTIO_SND(vdev);
771 VirtQueueElement *elem;
772 virtio_snd_ctrl_command *cmd;
773
774 trace_virtio_snd_handle_ctrl(vdev, vq);
775
776 if (!virtio_queue_ready(vq)) {
777 return;
778 }
779
780 elem = virtqueue_pop(vq, sizeof(VirtQueueElement));
781 while (elem) {
782 cmd = g_new0(virtio_snd_ctrl_command, 1);
783 cmd->elem = elem;
784 cmd->vq = vq;
785 cmd->resp.code = cpu_to_le32(VIRTIO_SND_S_OK);
786 /* implicit cmd->payload_size = 0; */
787 QTAILQ_INSERT_TAIL(&s->cmdq, cmd, next);
788 elem = virtqueue_pop(vq, sizeof(VirtQueueElement));
789 }
790
791 virtio_snd_process_cmdq(s);
792 }
793
794 /*
795 * The event virtqueue handler.
796 * Not implemented yet.
797 *
798 * @vdev: VirtIOSound device
799 * @vq: event vq
800 */
virtio_snd_handle_event(VirtIODevice * vdev,VirtQueue * vq)801 static void virtio_snd_handle_event(VirtIODevice *vdev, VirtQueue *vq)
802 {
803 qemu_log_mask(LOG_UNIMP, "virtio_snd: event queue is unimplemented.\n");
804 trace_virtio_snd_handle_event();
805 }
806
807 /*
808 * Must only be called if vsnd->invalid is not empty.
809 */
empty_invalid_queue(VirtIODevice * vdev,VirtQueue * vq)810 static inline void empty_invalid_queue(VirtIODevice *vdev, VirtQueue *vq)
811 {
812 VirtIOSoundPCMBuffer *buffer = NULL;
813 virtio_snd_pcm_status resp = { 0 };
814 VirtIOSound *vsnd = VIRTIO_SND(vdev);
815
816 g_assert(!QSIMPLEQ_EMPTY(&vsnd->invalid));
817
818 while (!QSIMPLEQ_EMPTY(&vsnd->invalid)) {
819 buffer = QSIMPLEQ_FIRST(&vsnd->invalid);
820 /* If buffer->vq != vq, our logic is fundamentally wrong, so bail out */
821 g_assert(buffer->vq == vq);
822
823 resp.status = cpu_to_le32(VIRTIO_SND_S_BAD_MSG);
824 iov_from_buf(buffer->elem->in_sg,
825 buffer->elem->in_num,
826 0,
827 &resp,
828 sizeof(virtio_snd_pcm_status));
829 virtqueue_push(vq,
830 buffer->elem,
831 sizeof(virtio_snd_pcm_status));
832 QSIMPLEQ_REMOVE_HEAD(&vsnd->invalid, entry);
833 virtio_snd_pcm_buffer_free(buffer);
834 }
835 /* Notify vq about virtio_snd_pcm_status responses. */
836 virtio_notify(vdev, vq);
837 }
838
839 /*
840 * The tx virtqueue handler. Makes the buffers available to their respective
841 * streams for consumption.
842 *
843 * @vdev: VirtIOSound device
844 * @vq: tx virtqueue
845 */
virtio_snd_handle_tx_xfer(VirtIODevice * vdev,VirtQueue * vq)846 static void virtio_snd_handle_tx_xfer(VirtIODevice *vdev, VirtQueue *vq)
847 {
848 VirtIOSound *vsnd = VIRTIO_SND(vdev);
849 VirtIOSoundPCMBuffer *buffer;
850 VirtQueueElement *elem;
851 size_t msg_sz, size;
852 virtio_snd_pcm_xfer hdr;
853 uint32_t stream_id;
854 /*
855 * If any of the I/O messages are invalid, put them in vsnd->invalid and
856 * return them after the for loop.
857 */
858 bool must_empty_invalid_queue = false;
859
860 if (!virtio_queue_ready(vq)) {
861 return;
862 }
863 trace_virtio_snd_handle_tx_xfer();
864
865 for (;;) {
866 VirtIOSoundPCMStream *stream;
867
868 elem = virtqueue_pop(vq, sizeof(VirtQueueElement));
869 if (!elem) {
870 break;
871 }
872 /* get the message hdr object */
873 msg_sz = iov_to_buf(elem->out_sg,
874 elem->out_num,
875 0,
876 &hdr,
877 sizeof(virtio_snd_pcm_xfer));
878 if (msg_sz != sizeof(virtio_snd_pcm_xfer)) {
879 goto tx_err;
880 }
881 stream_id = le32_to_cpu(hdr.stream_id);
882
883 if (stream_id >= vsnd->snd_conf.streams
884 || vsnd->pcm->streams[stream_id] == NULL) {
885 goto tx_err;
886 }
887
888 stream = vsnd->pcm->streams[stream_id];
889 if (stream->info.direction != VIRTIO_SND_D_OUTPUT) {
890 goto tx_err;
891 }
892
893 WITH_QEMU_LOCK_GUARD(&stream->queue_mutex) {
894 size = iov_size(elem->out_sg, elem->out_num) - msg_sz;
895
896 buffer = g_malloc0(sizeof(VirtIOSoundPCMBuffer) + size);
897 buffer->elem = elem;
898 buffer->populated = false;
899 buffer->vq = vq;
900 buffer->size = size;
901 buffer->offset = 0;
902
903 QSIMPLEQ_INSERT_TAIL(&stream->queue, buffer, entry);
904 }
905 continue;
906
907 tx_err:
908 must_empty_invalid_queue = true;
909 buffer = g_malloc0(sizeof(VirtIOSoundPCMBuffer));
910 buffer->elem = elem;
911 buffer->vq = vq;
912 QSIMPLEQ_INSERT_TAIL(&vsnd->invalid, buffer, entry);
913 }
914
915 if (must_empty_invalid_queue) {
916 empty_invalid_queue(vdev, vq);
917 }
918 }
919
920 /*
921 * The rx virtqueue handler. Makes the buffers available to their respective
922 * streams for consumption.
923 *
924 * @vdev: VirtIOSound device
925 * @vq: rx virtqueue
926 */
virtio_snd_handle_rx_xfer(VirtIODevice * vdev,VirtQueue * vq)927 static void virtio_snd_handle_rx_xfer(VirtIODevice *vdev, VirtQueue *vq)
928 {
929 VirtIOSound *vsnd = VIRTIO_SND(vdev);
930 VirtIOSoundPCMBuffer *buffer;
931 VirtQueueElement *elem;
932 size_t msg_sz, size;
933 virtio_snd_pcm_xfer hdr;
934 uint32_t stream_id;
935 /*
936 * if any of the I/O messages are invalid, put them in vsnd->invalid and
937 * return them after the for loop.
938 */
939 bool must_empty_invalid_queue = false;
940
941 if (!virtio_queue_ready(vq)) {
942 return;
943 }
944 trace_virtio_snd_handle_rx_xfer();
945
946 for (;;) {
947 VirtIOSoundPCMStream *stream;
948
949 elem = virtqueue_pop(vq, sizeof(VirtQueueElement));
950 if (!elem) {
951 break;
952 }
953 /* get the message hdr object */
954 msg_sz = iov_to_buf(elem->out_sg,
955 elem->out_num,
956 0,
957 &hdr,
958 sizeof(virtio_snd_pcm_xfer));
959 if (msg_sz != sizeof(virtio_snd_pcm_xfer)) {
960 goto rx_err;
961 }
962 stream_id = le32_to_cpu(hdr.stream_id);
963
964 if (stream_id >= vsnd->snd_conf.streams
965 || !vsnd->pcm->streams[stream_id]) {
966 goto rx_err;
967 }
968
969 stream = vsnd->pcm->streams[stream_id];
970 if (stream == NULL || stream->info.direction != VIRTIO_SND_D_INPUT) {
971 goto rx_err;
972 }
973 WITH_QEMU_LOCK_GUARD(&stream->queue_mutex) {
974 size = iov_size(elem->in_sg, elem->in_num) -
975 sizeof(virtio_snd_pcm_status);
976 buffer = g_malloc0(sizeof(VirtIOSoundPCMBuffer) + size);
977 buffer->elem = elem;
978 buffer->vq = vq;
979 buffer->size = 0;
980 buffer->offset = 0;
981 QSIMPLEQ_INSERT_TAIL(&stream->queue, buffer, entry);
982 }
983 continue;
984
985 rx_err:
986 must_empty_invalid_queue = true;
987 buffer = g_malloc0(sizeof(VirtIOSoundPCMBuffer));
988 buffer->elem = elem;
989 buffer->vq = vq;
990 QSIMPLEQ_INSERT_TAIL(&vsnd->invalid, buffer, entry);
991 }
992
993 if (must_empty_invalid_queue) {
994 empty_invalid_queue(vdev, vq);
995 }
996 }
997
get_features(VirtIODevice * vdev,uint64_t features,Error ** errp)998 static uint64_t get_features(VirtIODevice *vdev, uint64_t features,
999 Error **errp)
1000 {
1001 /*
1002 * virtio-v1.2-csd01, 5.14.3,
1003 * Feature Bits
1004 * None currently defined.
1005 */
1006 VirtIOSound *s = VIRTIO_SND(vdev);
1007 features |= s->features;
1008
1009 trace_virtio_snd_get_features(vdev, features);
1010
1011 return features;
1012 }
1013
1014 static void
virtio_snd_vm_state_change(void * opaque,bool running,RunState state)1015 virtio_snd_vm_state_change(void *opaque, bool running,
1016 RunState state)
1017 {
1018 if (running) {
1019 trace_virtio_snd_vm_state_running();
1020 } else {
1021 trace_virtio_snd_vm_state_stopped();
1022 }
1023 }
1024
virtio_snd_realize(DeviceState * dev,Error ** errp)1025 static void virtio_snd_realize(DeviceState *dev, Error **errp)
1026 {
1027 ERRP_GUARD();
1028 VirtIOSound *vsnd = VIRTIO_SND(dev);
1029 VirtIODevice *vdev = VIRTIO_DEVICE(dev);
1030 virtio_snd_pcm_set_params default_params = { 0 };
1031 uint32_t status;
1032
1033 trace_virtio_snd_realize(vsnd);
1034
1035 /* check number of jacks and streams */
1036 if (vsnd->snd_conf.jacks > 8) {
1037 error_setg(errp,
1038 "Invalid number of jacks: %"PRIu32,
1039 vsnd->snd_conf.jacks);
1040 return;
1041 }
1042 if (vsnd->snd_conf.streams < 1 || vsnd->snd_conf.streams > 10) {
1043 error_setg(errp,
1044 "Invalid number of streams: %"PRIu32,
1045 vsnd->snd_conf.streams);
1046 return;
1047 }
1048
1049 if (vsnd->snd_conf.chmaps > VIRTIO_SND_CHMAP_MAX_SIZE) {
1050 error_setg(errp,
1051 "Invalid number of channel maps: %"PRIu32,
1052 vsnd->snd_conf.chmaps);
1053 return;
1054 }
1055
1056 if (!AUD_register_card("virtio-sound", &vsnd->card, errp)) {
1057 return;
1058 }
1059
1060 vsnd->vmstate =
1061 qemu_add_vm_change_state_handler(virtio_snd_vm_state_change, vsnd);
1062
1063 vsnd->pcm = g_new0(VirtIOSoundPCM, 1);
1064 vsnd->pcm->snd = vsnd;
1065 vsnd->pcm->streams =
1066 g_new0(VirtIOSoundPCMStream *, vsnd->snd_conf.streams);
1067 vsnd->pcm->pcm_params =
1068 g_new0(virtio_snd_pcm_set_params, vsnd->snd_conf.streams);
1069
1070 virtio_init(vdev, VIRTIO_ID_SOUND, sizeof(virtio_snd_config));
1071 virtio_add_feature(&vsnd->features, VIRTIO_F_VERSION_1);
1072
1073 /* set default params for all streams */
1074 default_params.features = 0;
1075 default_params.buffer_bytes = cpu_to_le32(8192);
1076 default_params.period_bytes = cpu_to_le32(2048);
1077 default_params.channels = 2;
1078 default_params.format = VIRTIO_SND_PCM_FMT_S16;
1079 default_params.rate = VIRTIO_SND_PCM_RATE_48000;
1080 vsnd->queues[VIRTIO_SND_VQ_CONTROL] =
1081 virtio_add_queue(vdev, 64, virtio_snd_handle_ctrl);
1082 vsnd->queues[VIRTIO_SND_VQ_EVENT] =
1083 virtio_add_queue(vdev, 64, virtio_snd_handle_event);
1084 vsnd->queues[VIRTIO_SND_VQ_TX] =
1085 virtio_add_queue(vdev, 64, virtio_snd_handle_tx_xfer);
1086 vsnd->queues[VIRTIO_SND_VQ_RX] =
1087 virtio_add_queue(vdev, 64, virtio_snd_handle_rx_xfer);
1088 qemu_mutex_init(&vsnd->cmdq_mutex);
1089 QTAILQ_INIT(&vsnd->cmdq);
1090 QSIMPLEQ_INIT(&vsnd->invalid);
1091
1092 for (uint32_t i = 0; i < vsnd->snd_conf.streams; i++) {
1093 status = virtio_snd_set_pcm_params(vsnd, i, &default_params);
1094 if (status != cpu_to_le32(VIRTIO_SND_S_OK)) {
1095 error_setg(errp,
1096 "Can't initialize stream params, device responded with %s.",
1097 print_code(status));
1098 goto error_cleanup;
1099 }
1100 status = virtio_snd_pcm_prepare(vsnd, i);
1101 if (status != cpu_to_le32(VIRTIO_SND_S_OK)) {
1102 error_setg(errp,
1103 "Can't prepare streams, device responded with %s.",
1104 print_code(status));
1105 goto error_cleanup;
1106 }
1107 }
1108
1109 return;
1110
1111 error_cleanup:
1112 virtio_snd_unrealize(dev);
1113 }
1114
return_tx_buffer(VirtIOSoundPCMStream * stream,VirtIOSoundPCMBuffer * buffer)1115 static inline void return_tx_buffer(VirtIOSoundPCMStream *stream,
1116 VirtIOSoundPCMBuffer *buffer)
1117 {
1118 virtio_snd_pcm_status resp = { 0 };
1119 resp.status = cpu_to_le32(VIRTIO_SND_S_OK);
1120 resp.latency_bytes = cpu_to_le32((uint32_t)buffer->size);
1121 iov_from_buf(buffer->elem->in_sg,
1122 buffer->elem->in_num,
1123 0,
1124 &resp,
1125 sizeof(virtio_snd_pcm_status));
1126 virtqueue_push(buffer->vq,
1127 buffer->elem,
1128 sizeof(virtio_snd_pcm_status));
1129 virtio_notify(VIRTIO_DEVICE(stream->s), buffer->vq);
1130 QSIMPLEQ_REMOVE(&stream->queue,
1131 buffer,
1132 VirtIOSoundPCMBuffer,
1133 entry);
1134 virtio_snd_pcm_buffer_free(buffer);
1135 }
1136
1137 /*
1138 * AUD_* output callback.
1139 *
1140 * @data: VirtIOSoundPCMStream stream
1141 * @available: number of bytes that can be written with AUD_write()
1142 */
virtio_snd_pcm_out_cb(void * data,int available)1143 static void virtio_snd_pcm_out_cb(void *data, int available)
1144 {
1145 VirtIOSoundPCMStream *stream = data;
1146 VirtIOSoundPCMBuffer *buffer;
1147 size_t size;
1148
1149 WITH_QEMU_LOCK_GUARD(&stream->queue_mutex) {
1150 while (!QSIMPLEQ_EMPTY(&stream->queue)) {
1151 buffer = QSIMPLEQ_FIRST(&stream->queue);
1152 if (!virtio_queue_ready(buffer->vq)) {
1153 return;
1154 }
1155 if (!stream->active) {
1156 /* Stream has stopped, so do not perform AUD_write. */
1157 return_tx_buffer(stream, buffer);
1158 continue;
1159 }
1160 if (!buffer->populated) {
1161 iov_to_buf(buffer->elem->out_sg,
1162 buffer->elem->out_num,
1163 sizeof(virtio_snd_pcm_xfer),
1164 buffer->data,
1165 buffer->size);
1166 buffer->populated = true;
1167 }
1168 for (;;) {
1169 size = AUD_write(stream->voice.out,
1170 buffer->data + buffer->offset,
1171 MIN(buffer->size, available));
1172 assert(size <= MIN(buffer->size, available));
1173 if (size == 0) {
1174 /* break out of both loops */
1175 available = 0;
1176 break;
1177 }
1178 buffer->size -= size;
1179 buffer->offset += size;
1180 available -= size;
1181 if (buffer->size < 1) {
1182 return_tx_buffer(stream, buffer);
1183 break;
1184 }
1185 if (!available) {
1186 break;
1187 }
1188 }
1189 if (!available) {
1190 break;
1191 }
1192 }
1193 }
1194 }
1195
1196 /*
1197 * Flush all buffer data from this input stream's queue into the driver's
1198 * virtual queue.
1199 *
1200 * @stream: VirtIOSoundPCMStream *stream
1201 */
return_rx_buffer(VirtIOSoundPCMStream * stream,VirtIOSoundPCMBuffer * buffer)1202 static inline void return_rx_buffer(VirtIOSoundPCMStream *stream,
1203 VirtIOSoundPCMBuffer *buffer)
1204 {
1205 virtio_snd_pcm_status resp = { 0 };
1206 resp.status = cpu_to_le32(VIRTIO_SND_S_OK);
1207 resp.latency_bytes = 0;
1208 /* Copy data -if any- to guest */
1209 iov_from_buf(buffer->elem->in_sg,
1210 buffer->elem->in_num,
1211 0,
1212 buffer->data,
1213 buffer->size);
1214 iov_from_buf(buffer->elem->in_sg,
1215 buffer->elem->in_num,
1216 buffer->size,
1217 &resp,
1218 sizeof(virtio_snd_pcm_status));
1219 virtqueue_push(buffer->vq,
1220 buffer->elem,
1221 sizeof(virtio_snd_pcm_status) + buffer->size);
1222 virtio_notify(VIRTIO_DEVICE(stream->s), buffer->vq);
1223 QSIMPLEQ_REMOVE(&stream->queue,
1224 buffer,
1225 VirtIOSoundPCMBuffer,
1226 entry);
1227 virtio_snd_pcm_buffer_free(buffer);
1228 }
1229
1230
1231 /*
1232 * AUD_* input callback.
1233 *
1234 * @data: VirtIOSoundPCMStream stream
1235 * @available: number of bytes that can be read with AUD_read()
1236 */
virtio_snd_pcm_in_cb(void * data,int available)1237 static void virtio_snd_pcm_in_cb(void *data, int available)
1238 {
1239 VirtIOSoundPCMStream *stream = data;
1240 VirtIOSoundPCMBuffer *buffer;
1241 size_t size, max_size;
1242
1243 WITH_QEMU_LOCK_GUARD(&stream->queue_mutex) {
1244 while (!QSIMPLEQ_EMPTY(&stream->queue)) {
1245 buffer = QSIMPLEQ_FIRST(&stream->queue);
1246 if (!virtio_queue_ready(buffer->vq)) {
1247 return;
1248 }
1249 if (!stream->active) {
1250 /* Stream has stopped, so do not perform AUD_read. */
1251 return_rx_buffer(stream, buffer);
1252 continue;
1253 }
1254
1255 max_size = iov_size(buffer->elem->in_sg, buffer->elem->in_num);
1256 for (;;) {
1257 if (buffer->size >= max_size) {
1258 return_rx_buffer(stream, buffer);
1259 break;
1260 }
1261 size = AUD_read(stream->voice.in,
1262 buffer->data + buffer->size,
1263 MIN(available, (stream->params.period_bytes -
1264 buffer->size)));
1265 if (!size) {
1266 available = 0;
1267 break;
1268 }
1269 buffer->size += size;
1270 available -= size;
1271 if (buffer->size >= stream->params.period_bytes) {
1272 return_rx_buffer(stream, buffer);
1273 break;
1274 }
1275 if (!available) {
1276 break;
1277 }
1278 }
1279 if (!available) {
1280 break;
1281 }
1282 }
1283 }
1284 }
1285
1286 /*
1287 * Flush all buffer data from this output stream's queue into the driver's
1288 * virtual queue.
1289 *
1290 * @stream: VirtIOSoundPCMStream *stream
1291 */
virtio_snd_pcm_flush(VirtIOSoundPCMStream * stream)1292 static inline void virtio_snd_pcm_flush(VirtIOSoundPCMStream *stream)
1293 {
1294 VirtIOSoundPCMBuffer *buffer;
1295 void (*cb)(VirtIOSoundPCMStream *, VirtIOSoundPCMBuffer *) =
1296 (stream->info.direction == VIRTIO_SND_D_OUTPUT) ? return_tx_buffer :
1297 return_rx_buffer;
1298
1299 WITH_QEMU_LOCK_GUARD(&stream->queue_mutex) {
1300 while (!QSIMPLEQ_EMPTY(&stream->queue)) {
1301 buffer = QSIMPLEQ_FIRST(&stream->queue);
1302 cb(stream, buffer);
1303 }
1304 }
1305 }
1306
virtio_snd_unrealize(DeviceState * dev)1307 static void virtio_snd_unrealize(DeviceState *dev)
1308 {
1309 VirtIODevice *vdev = VIRTIO_DEVICE(dev);
1310 VirtIOSound *vsnd = VIRTIO_SND(dev);
1311 VirtIOSoundPCMStream *stream;
1312
1313 qemu_del_vm_change_state_handler(vsnd->vmstate);
1314 trace_virtio_snd_unrealize(vsnd);
1315
1316 if (vsnd->pcm) {
1317 if (vsnd->pcm->streams) {
1318 for (uint32_t i = 0; i < vsnd->snd_conf.streams; i++) {
1319 stream = vsnd->pcm->streams[i];
1320 if (stream) {
1321 virtio_snd_process_cmdq(stream->s);
1322 virtio_snd_pcm_close(stream);
1323 qemu_mutex_destroy(&stream->queue_mutex);
1324 g_free(stream);
1325 }
1326 }
1327 g_free(vsnd->pcm->streams);
1328 }
1329 g_free(vsnd->pcm->pcm_params);
1330 g_free(vsnd->pcm);
1331 vsnd->pcm = NULL;
1332 }
1333 AUD_remove_card(&vsnd->card);
1334 qemu_mutex_destroy(&vsnd->cmdq_mutex);
1335 virtio_delete_queue(vsnd->queues[VIRTIO_SND_VQ_CONTROL]);
1336 virtio_delete_queue(vsnd->queues[VIRTIO_SND_VQ_EVENT]);
1337 virtio_delete_queue(vsnd->queues[VIRTIO_SND_VQ_TX]);
1338 virtio_delete_queue(vsnd->queues[VIRTIO_SND_VQ_RX]);
1339 virtio_cleanup(vdev);
1340 }
1341
1342
virtio_snd_reset(VirtIODevice * vdev)1343 static void virtio_snd_reset(VirtIODevice *vdev)
1344 {
1345 VirtIOSound *vsnd = VIRTIO_SND(vdev);
1346 virtio_snd_ctrl_command *cmd;
1347
1348 /*
1349 * Sanity check that the invalid buffer message queue is emptied at the end
1350 * of every virtio_snd_handle_tx_xfer/virtio_snd_handle_rx_xfer call, and
1351 * must be empty otherwise.
1352 */
1353 g_assert(QSIMPLEQ_EMPTY(&vsnd->invalid));
1354
1355 WITH_QEMU_LOCK_GUARD(&vsnd->cmdq_mutex) {
1356 while (!QTAILQ_EMPTY(&vsnd->cmdq)) {
1357 cmd = QTAILQ_FIRST(&vsnd->cmdq);
1358 QTAILQ_REMOVE(&vsnd->cmdq, cmd, next);
1359 virtio_snd_ctrl_cmd_free(cmd);
1360 }
1361 }
1362 }
1363
virtio_snd_class_init(ObjectClass * klass,const void * data)1364 static void virtio_snd_class_init(ObjectClass *klass, const void *data)
1365 {
1366 DeviceClass *dc = DEVICE_CLASS(klass);
1367 VirtioDeviceClass *vdc = VIRTIO_DEVICE_CLASS(klass);
1368
1369
1370 set_bit(DEVICE_CATEGORY_SOUND, dc->categories);
1371 device_class_set_props(dc, virtio_snd_properties);
1372
1373 dc->vmsd = &vmstate_virtio_snd;
1374 vdc->vmsd = &vmstate_virtio_snd_device;
1375 vdc->realize = virtio_snd_realize;
1376 vdc->unrealize = virtio_snd_unrealize;
1377 vdc->get_config = virtio_snd_get_config;
1378 vdc->get_features = get_features;
1379 vdc->reset = virtio_snd_reset;
1380 vdc->legacy_features = 0;
1381 }
1382
1383 static const TypeInfo virtio_snd_types[] = {
1384 {
1385 .name = TYPE_VIRTIO_SND,
1386 .parent = TYPE_VIRTIO_DEVICE,
1387 .instance_size = sizeof(VirtIOSound),
1388 .class_init = virtio_snd_class_init,
1389 }
1390 };
1391
1392 DEFINE_TYPES(virtio_snd_types)
1393