1- #include <stdio.h>
2- #include <string.h>
31#include <math.h>
42#include <pthread.h>
3+ #include <stdio.h>
4+ #include <string.h>
55
66#define CNFA_IMPLEMENTATION
77#include "CNFA_sf.h"
@@ -246,7 +246,9 @@ typedef struct {
246246} virtio_snd_prop_t ;
247247
248248static virtio_snd_config_t vsnd_configs [VSND_DEV_CNT_MAX ];
249- static virtio_snd_prop_t vsnd_props [VSND_DEV_CNT_MAX ];
249+ static virtio_snd_prop_t vsnd_props [VSND_DEV_CNT_MAX ] = {
250+ [0 ... VSND_DEV_CNT_MAX - 1 ].pp .hdr .hdr .code = VIRTIO_SND_R_PCM_SET_PARAMS ,
251+ };
250252static int vsnd_dev_cnt = 0 ;
251253
252254typedef struct {
@@ -372,12 +374,20 @@ static void virtio_snd_read_chmap_info_handler(
372374static void virtio_snd_read_pcm_set_params (struct virtq_desc * vq_desc ,
373375 const virtio_snd_query_info_t * query )
374376{
377+ virtio_snd_pcm_set_params_t * request = query ;
378+ uint32_t id = request -> hdr .stream_id ;
375379 /* TODO: detect current state of stream */
380+ uint32_t code = vsnd_props [id ].pp .hdr .hdr .code ;
381+ if (code != VIRTIO_SND_R_PCM_RELEASE &&
382+ code != VIRTIO_SND_R_PCM_SET_PARAMS &&
383+ code != VIRTIO_SND_R_PCM_PREPARE ) {
384+ fprintf (stderr ,
385+ "virtio_snd_pcm_set_params with invalid previous state %#08x\n" ,
386+ code );
387+ return ;
388+ }
376389 /* TODO: check the valiability of buffer_bytes, period_bytes, channel_min,
377390 * and channel_max */
378-
379- virtio_snd_pcm_set_params_t * request = query ;
380- uint32_t id = request -> hdr .stream_id ;
381391 vsnd_props [id ].pp .hdr .hdr .code = VIRTIO_SND_R_PCM_SET_PARAMS ;
382392 vsnd_props [id ].pp .buffer_bytes = request -> buffer_bytes ;
383393 vsnd_props [id ].pp .period_bytes = request -> period_bytes ;
@@ -395,6 +405,17 @@ static void virtio_snd_read_pcm_prepare(struct virtq_desc *vq_desc,
395405{
396406 virtio_snd_pcm_hdr_t * request = query ;
397407 uint32_t stream_id = request -> stream_id ;
408+ uint32_t code = vsnd_props [stream_id ].pp .hdr .hdr .code ;
409+ if (code != VIRTIO_SND_R_PCM_RELEASE &&
410+ code != VIRTIO_SND_R_PCM_SET_PARAMS &&
411+ code != VIRTIO_SND_R_PCM_PREPARE ) {
412+ fprintf (
413+ stderr ,
414+ "virtio_snd_read_pcm_prepare with invalid previous state %#08x\n" ,
415+ code );
416+ return ;
417+ }
418+
398419 vsnd_props [stream_id ].pp .hdr .hdr .code = VIRTIO_SND_R_PCM_PREPARE ;
399420 vsnd_props [stream_id ].audio_host =
400421 CNFAInit (NULL , "semu-virtio-snd" , virtio_snd_cb , 44100 , 0 , 1 , 0 ,
@@ -415,11 +436,21 @@ static void virtio_snd_read_pcm_prepare(struct virtq_desc *vq_desc,
415436static void virtio_snd_read_pcm_start (struct virtq_desc * vq_desc ,
416437 const virtio_snd_query_info_t * query )
417438{
418- /* TODO: let application to set stream_id at will */
439+ virtio_snd_pcm_hdr_t * request = query ;
440+ uint32_t stream_id = request -> stream_id ;
441+ uint32_t code = vsnd_props [stream_id ].pp .hdr .hdr .code ;
442+ if (code != VIRTIO_SND_R_PCM_PREPARE && code != VIRTIO_SND_R_PCM_STOP ) {
443+ fprintf (
444+ stderr ,
445+ "virtio_snd_read_pcm_start with previous invalide state %#08x\n" ,
446+ code );
447+ return ;
448+ }
419449
420450 /* Control the callback to start playing */
421451 /* TODO: add lock to avoid race condition */
422452 pthread_mutex_lock (& virtio_snd_mutex );
453+ vsnd_props [stream_id ].pp .hdr .hdr .code = VIRTIO_SND_R_PCM_START ;
423454 v .guest_playing = true;
424455 pthread_mutex_unlock (& virtio_snd_mutex );
425456
@@ -429,10 +460,20 @@ static void virtio_snd_read_pcm_start(struct virtq_desc *vq_desc,
429460static void virtio_snd_read_pcm_stop (struct virtq_desc * vq_desc ,
430461 const virtio_snd_query_info_t * query )
431462{
432- /* TODO: let application to set stream_id at will */
463+ virtio_snd_pcm_hdr_t * request = query ;
464+ uint32_t stream_id = request -> stream_id ;
465+ uint32_t code = vsnd_props [stream_id ].pp .hdr .hdr .code ;
466+ if (code != VIRTIO_SND_R_PCM_START ) {
467+ fprintf (stderr ,
468+ "virtio_snd_read_pcm_stop with previous invalide state %#08x\n" ,
469+ code );
470+ return ;
471+ }
472+
433473 /* Control the callback to stop playing */
434474 /* TODO: add lock to avoid race condition */
435475 pthread_mutex_lock (& virtio_snd_mutex );
476+ vsnd_props [stream_id ].pp .hdr .hdr .code = VIRTIO_SND_R_PCM_STOP ;
436477 v .guest_playing = false;
437478 pthread_mutex_lock (& virtio_snd_mutex );
438479
@@ -442,14 +483,22 @@ static void virtio_snd_read_pcm_stop(struct virtq_desc *vq_desc,
442483static void virtio_snd_read_pcm_release (struct virtq_desc * vq_desc ,
443484 const virtio_snd_query_info_t * query )
444485{
486+ virtio_snd_pcm_hdr_t * request = query ;
487+ uint32_t stream_id = request -> stream_id ;
488+ uint32_t code = vsnd_props [stream_id ].pp .hdr .hdr .code ;
489+ if (code != VIRTIO_SND_R_PCM_PREPARE && code != VIRTIO_SND_R_PCM_STOP ) {
490+ fprintf (
491+ stderr ,
492+ "virtio_snd_read_pcm_release with previous invalide state %#08x\n" ,
493+ code );
494+ return ;
495+ }
445496 /* Control the callback to stop playing */
446497 /* TODO: add lock to avoid race condition */
447498 pthread_mutex_lock (& virtio_snd_mutex );
448499 v .guest_playing = false;
449500 pthread_mutex_unlock (& virtio_snd_mutex );
450501
451- virtio_snd_pcm_hdr_t * request = query ;
452- uint32_t stream_id = request -> stream_id ;
453502 vsnd_props [stream_id ].pp .hdr .hdr .code = VIRTIO_SND_R_PCM_RELEASE ;
454503 CNFAClose (vsnd_props [stream_id ].audio_host );
455504 free (vsnd_props [stream_id ].buf );
@@ -482,23 +531,21 @@ static void virtio_snd_cb(struct CNFADriver *dev,
482531 vsnd_stream_sel_t * v_ptr = (vsnd_stream_sel_t * ) dev -> opaque ;
483532 bool playing = v_ptr -> guest_playing ;
484533
485- if (!playing ) {
486- fprintf (stderr , "notplaying\n" );
487- return ;
488- }
534+ if (!playing ) {
535+ fprintf (stderr , "notplaying\n" );
536+ return ;
537+ }
489538
490- int channels = dev -> channelsPlay ;
491- for (int i = 0 ; i < framesp ; i ++ )
492- {
539+ int channels = dev -> channelsPlay ;
540+ for (int i = 0 ; i < framesp ; i ++ ) {
493541 // Shift phase, so we run at 440 Hz (A4)
494- omega += ( 3.14159 * 2 * 440. ) / dev -> spsPlay ;
542+ omega += (3.14159 * 2 * 440. ) / dev -> spsPlay ;
495543
496- // Make the 440 Hz tone at 10% volume and convert to short.
497- short value = sin ( omega ) * 0.1 * 32767 ;
544+ // Make the 440 Hz tone at 10% volume and convert to short.
545+ short value = sin (omega ) * 0.1 * 32767 ;
498546
499547 int c ;
500- for ( c = 0 ; c < channels ; c ++ )
501- {
548+ for (c = 0 ; c < channels ; c ++ ) {
502549 * (out ++ ) = value ;
503550 }
504551 }
@@ -827,10 +874,10 @@ static bool virtio_snd_reg_write(virtio_snd_state_t *vsnd,
827874 virtio_snd_desc_handler );
828875 break ;
829876 case VSND_QUEUE_TX :
830- fprintf (stderr , "TX start\n" );
877+ fprintf (stderr , "TX start\n" );
831878 /*virtio_queue_notify_handler(vsnd, value,
832879 virtio_snd_tx_desc_handler);*/
833- fprintf (stderr , "TX end\n" );
880+ fprintf (stderr , "TX end\n" );
834881 break ;
835882 case VSND_QUEUE_EVT :
836883 fprintf (stderr , "EVT\n" );
0 commit comments