Skip to content

Commit 60b6362

Browse files
committed
Add FSM of snd_pcm_*
1 parent f0f9978 commit 60b6362

File tree

1 file changed

+71
-24
lines changed

1 file changed

+71
-24
lines changed

virtio-snd.c

Lines changed: 71 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
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

248248
static 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+
};
250252
static int vsnd_dev_cnt = 0;
251253

252254
typedef struct {
@@ -372,12 +374,20 @@ static void virtio_snd_read_chmap_info_handler(
372374
static 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,
415436
static 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,
429460
static 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,
442483
static 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

Comments
 (0)