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