Skip to content

Commit 24edae8

Browse files
committed
Set to correct size of memcpy
1 parent c35c5ed commit 24edae8

File tree

1 file changed

+119
-2
lines changed

1 file changed

+119
-2
lines changed

virtio-snd.c

Lines changed: 119 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -514,6 +514,120 @@ static uint32_t flush_stream_id = 0;
514514

515515
VSND_GEN_TX_QUEUE_HANDLER(normal, 1);
516516
VSND_GEN_TX_QUEUE_HANDLER(flush, 0);
517+
#if 0
518+
#define VSND_GEN_RX_QUEUE_HANDLER(NAME_SUFFIX, WRITE) \
519+
static int virtio_snd_rx_desc_##NAME_SUFFIX##_handler( \
520+
virtio_snd_state_t *vsnd, const virtio_snd_queue_t *queue, \
521+
uint32_t desc_idx, uint32_t *plen) \
522+
{ \
523+
/* A PCM I/O message uses at least 3 virtqueue descriptors to \
524+
* represent a PCM data of a period size. \
525+
* The first part contains one descriptor as follows: \
526+
* struct virtio_snd_pcm_xfer \
527+
* The second part contains one or more descriptors \
528+
* representing PCM frames. \
529+
* the last part contains one descriptor as follows: \
530+
* struct virtio_snd_pcm_status \
531+
*/ \
532+
virtq_desc_queue_node_t *node; \
533+
struct list_head q; \
534+
INIT_LIST_HEAD(&q); \
535+
\
536+
/* Collect the descriptors */ \
537+
int cnt = 0; \
538+
for (;;) { \
539+
/* The size of the `struct virtq_desc` is 4 words */ \
540+
const uint32_t *desc = \
541+
&vsnd->ram[queue->QueueDesc + desc_idx * 4]; \
542+
\
543+
/* Retrieve the fields of current descriptor */ \
544+
node = (virtq_desc_queue_node_t *) malloc(sizeof(*node)); \
545+
node->vq_desc.addr = desc[0]; \
546+
node->vq_desc.len = desc[2]; \
547+
node->vq_desc.flags = desc[3]; \
548+
list_push(&node->q, &q); \
549+
desc_idx = desc[3] >> 16; /* vq_desc[desc_cnt].next */ \
550+
\
551+
cnt++; \
552+
\
553+
/* Leave the loop if next-flag is not set */ \
554+
if (!(desc[3] & VIRTIO_DESC_F_NEXT)) \
555+
break; \
556+
} \
557+
\
558+
int idx = 0; \
559+
uint32_t stream_id = 0; /* Explicitly set the stream_id */ \
560+
uintptr_t base = (uintptr_t) vsnd->ram; \
561+
uint32_t ret_len = 0; \
562+
uint8_t bad_msg_err = 0; \
563+
list_for_each_entry (node, &q, q) { \
564+
uint32_t addr = node->vq_desc.addr; \
565+
uint32_t len = node->vq_desc.len; \
566+
if (idx == 0) { /* the first descriptor */ \
567+
const virtio_snd_pcm_xfer_t *request = \
568+
(virtio_snd_pcm_xfer_t *) (base + addr); \
569+
stream_id = request->stream_id; \
570+
IIF(WRITE) \
571+
(/* enqueue frames */ \
572+
bad_msg_err = stream_id >= VSND_DEV_CNT_MAX ? 1 : 0; \
573+
, /* flush queue */ \
574+
bad_msg_err = stream_id != flush_stream_id \
575+
? 1 \
576+
: 0; /* select only stream_id 0 */ \
577+
) goto early_continue; \
578+
} else if (idx == cnt - 1) { /* the last descriptor */ \
579+
IIF(WRITE) \
580+
( /* enqueue frames */ \
581+
, /* flush queue */ \
582+
if (bad_msg_err == 1) { \
583+
fprintf(stderr, "ignore flush stream_id %" PRIu32 "\n", \
584+
stream_id); \
585+
goto early_continue; \
586+
} fprintf(stderr, "flush stream_id %" PRIu32 "\n", \
587+
stream_id);) virtio_snd_pcm_status_t *response = \
588+
(virtio_snd_pcm_status_t *) (base + addr); \
589+
response->status = \
590+
bad_msg_err ? VIRTIO_SND_S_IO_ERR : VIRTIO_SND_S_OK; \
591+
response->latency_bytes = ret_len; \
592+
*plen = sizeof(*response); \
593+
goto early_continue; \
594+
} \
595+
\
596+
IIF(WRITE) \
597+
(/* enqueue frames */ \
598+
void *payload = (void *) (base + addr); if (bad_msg_err == 0) \
599+
/*__virtio_snd_frame_enqueue(payload, len, stream_id);*/ \
600+
, /* flush queue */ \
601+
(void) stream_id; \
602+
/* Suppress unused variable warning. */) ret_len += len; \
603+
\
604+
early_continue: \
605+
idx++; \
606+
} \
607+
\
608+
if (bad_msg_err != 0) \
609+
goto finally; \
610+
IIF(WRITE) \
611+
(/* enque frames */ \
612+
virtio_snd_prop_t *props = &vsnd_props[stream_id]; \
613+
props->lock.buf_ev_notity++; \
614+
pthread_cond_signal(&props->lock.readable);, /* flush queue */ \
615+
) \
616+
\
617+
/* Tear down the descriptor list and free space. */ \
618+
virtq_desc_queue_node_t *tmp = NULL; \
619+
list_for_each_entry_safe (node, tmp, &q, q) { \
620+
list_del(&node->q); \
621+
free(node); \
622+
} \
623+
\
624+
finally: \
625+
return 0; \
626+
}
627+
628+
VSND_GEN_RX_QUEUE_HANDLER(normal, 1);
629+
#endif
630+
#if 1
517631
static int virtio_snd_rx_desc_normal_handler(virtio_snd_state_t *vsnd,
518632
const virtio_snd_queue_t *queue,
519633
uint32_t desc_idx,
@@ -527,6 +641,7 @@ static int virtio_snd_rx_desc_normal_handler(virtio_snd_state_t *vsnd,
527641
/* send interrupt, unless VIRTQ_AVAIL_F_NO_INTERRUPT is set */
528642
return 0;
529643
}
644+
#endif
530645

531646
static void virtio_snd_set_fail(virtio_snd_state_t *vsnd)
532647
{
@@ -691,6 +806,8 @@ static void virtio_snd_read_pcm_prepare(const virtio_snd_pcm_hdr_t *query,
691806
uint32_t cnfa_period_bytes = bps_rate / 10;
692807
/* Calculate the period size (in frames) for CNFA . */
693808
uint32_t cnfa_period_frames = cnfa_period_bytes / VSND_CNFA_FRAME_SZ;
809+
fprintf(stderr, "period_bytes %" PRIu32 " period_frames %" PRIu32 "\n",
810+
cnfa_period_bytes, cnfa_period_frames);
694811

695812
INIT_LIST_HEAD(&props->buf_queue_head);
696813
props->intermediate =
@@ -909,9 +1026,9 @@ static int virtio_snd_rx_stream_cb(const void *input,
9091026
int channels = props->pp.channels;
9101027
uint32_t out_buf_sz = frame_cnt * channels;
9111028
uint32_t out_buf_bytes = out_buf_sz * VSND_CNFA_FRAME_SZ;
912-
uint32_t period_bytes = props->pp.period_bytes;
1029+
fprintf(stderr, "out_buf_bytes %" PRIu32 "\n", out_buf_bytes);
9131030
//__virtio_snd_frame_enqueue(output, out_buf_bytes, id);
914-
memcpy(props->intermediate, input, period_bytes);
1031+
memcpy(props->intermediate, input, out_buf_bytes);
9151032
fprintf(stderr, "+++ virtio_snd_rx_stream_cb +++\n");
9161033

9171034
return paContinue;

0 commit comments

Comments
 (0)