@@ -514,6 +514,120 @@ static uint32_t flush_stream_id = 0;
514514
515515VSND_GEN_TX_QUEUE_HANDLER (normal , 1 );
516516VSND_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
517631static 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
531646static 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