@@ -394,6 +394,12 @@ static void virtio_queue_notify_handler(virtio_snd_state_t *vsnd,
394394static void __virtio_snd_frame_enqueue (void * payload ,
395395 uint32_t n ,
396396 uint32_t stream_id );
397+ static void __virtio_snd_rx_frame_enqueue (void * payload ,
398+ uint32_t n ,
399+ uint32_t stream_id );
400+ static void __virtio_snd_rx_frame_dequeue (void * out ,
401+ uint32_t n ,
402+ uint32_t stream_id );
397403typedef struct {
398404 struct virtq_desc vq_desc ;
399405 struct list_head q ;
@@ -562,11 +568,9 @@ VSND_GEN_TX_QUEUE_HANDLER(flush, 0);
562568 uintptr_t base = (uintptr_t ) vsnd -> ram ; \
563569 uint32_t ret_len = 0 ; \
564570 uint8_t bad_msg_err = 0 ; \
565- fprintf (stderr , "*** rx_normal cnt %d\n" , cnt ); \
566571 list_for_each_entry (node , & q , q ) { \
567572 uint32_t addr = node -> vq_desc .addr ; \
568573 uint32_t len = node -> vq_desc .len ; \
569- fprintf (stderr , "*** rx_normal idx %" PRIu32 "\n" , len ); \
570574 if (idx == 0 ) { /* the first descriptor */ \
571575 const virtio_snd_pcm_xfer_t * request = \
572576 (virtio_snd_pcm_xfer_t * ) (base + addr ); \
@@ -592,15 +596,16 @@ VSND_GEN_TX_QUEUE_HANDLER(flush, 0);
592596 (virtio_snd_pcm_status_t * ) (base + addr ); \
593597 response -> status = \
594598 bad_msg_err ? VIRTIO_SND_S_IO_ERR : VIRTIO_SND_S_OK ; \
595- response -> latency_bytes = ret_len ; \
599+ response -> latency_bytes = 0 ; \
596600 * plen = sizeof (virtio_snd_pcm_status_t ) + ret_len ; \
601+ fprintf (stderr , "*** rx get %" PRIu32 " bytes \n" , * plen ); \
597602 goto early_continue ; \
598603 } \
599604 \
600605 IIF (WRITE ) \
601606 (/* enqueue frames */ \
602607 void * payload = (void * ) (base + addr ); if (bad_msg_err == 0 ) \
603- /*__virtio_snd_frame_enqueue (payload, len, stream_id);*/ \
608+ __virtio_snd_rx_frame_dequeue (payload , len , stream_id ); \
604609 , /* flush queue */ \
605610 (void ) stream_id ; \
606611 /* Suppress unused variable warning. */ ) ret_len += len ; \
@@ -614,8 +619,8 @@ VSND_GEN_TX_QUEUE_HANDLER(flush, 0);
614619 IIF (WRITE ) \
615620 (/* enque frames */ \
616621 virtio_snd_prop_t * props = & vsnd_props [stream_id ]; \
617- props -> lock .buf_ev_notity ++ ; \
618- pthread_cond_signal (& props -> lock .readable );, /* flush queue */ \
622+ /* props->lock.buf_ev_notity++;*/ \
623+ /* pthread_cond_signal(&props->lock.readable);*/ , /* flush queue */ \
619624 ) \
620625 \
621626 /* Tear down the descriptor list and free space. */ \
@@ -845,6 +850,8 @@ static void virtio_snd_read_pcm_prepare(const virtio_snd_pcm_hdr_t *query,
845850 }
846851
847852 * plen = 0 ;
853+
854+ fprintf (stderr , "=== pcm_prepare \n" );
848855}
849856
850857static void virtio_snd_read_pcm_start (const virtio_snd_pcm_hdr_t * query ,
@@ -872,6 +879,8 @@ static void virtio_snd_read_pcm_start(const virtio_snd_pcm_hdr_t *query,
872879 }
873880
874881 * plen = 0 ;
882+
883+ fprintf (stderr , "=== pcm_start \n" );
875884}
876885
877886static void virtio_snd_read_pcm_stop (const virtio_snd_pcm_hdr_t * query ,
@@ -899,6 +908,8 @@ static void virtio_snd_read_pcm_stop(const virtio_snd_pcm_hdr_t *query,
899908 }
900909
901910 * plen = 0 ;
911+
912+ fprintf (stderr , "=== pcm_stop\n" );
902913}
903914
904915static void virtio_snd_read_pcm_release (const virtio_snd_pcm_hdr_t * query ,
@@ -996,6 +1007,42 @@ static void __virtio_snd_frame_dequeue(void *out,
9961007 pthread_mutex_unlock (& props -> lock .lock );
9971008}
9981009
1010+ static void __virtio_snd_rx_frame_dequeue (void * out ,
1011+ uint32_t n ,
1012+ uint32_t stream_id )
1013+ {
1014+ virtio_snd_prop_t * props = & vsnd_props [stream_id ];
1015+
1016+ pthread_mutex_lock (& props -> lock .lock );
1017+ while (props -> lock .buf_ev_notity < 1 )
1018+ pthread_cond_wait (& props -> lock .readable , & props -> lock .lock );
1019+
1020+ /* Get the PCM frames from queue */
1021+ uint32_t written_bytes = 0 ;
1022+ while (!list_empty (& props -> buf_queue_head ) && written_bytes < n ) {
1023+ vsnd_buf_queue_node_t * node =
1024+ list_first_entry (& props -> buf_queue_head , vsnd_buf_queue_node_t , q );
1025+ uint32_t left = n - written_bytes ;
1026+ uint32_t actual = node -> len - node -> pos ;
1027+ uint32_t len =
1028+ left < actual ? left : actual ; /* Naive min implementation */
1029+
1030+ memcpy (props -> intermediate + written_bytes , node -> addr + node -> pos ,
1031+ len );
1032+
1033+ written_bytes += len ;
1034+ node -> pos += len ;
1035+ if (node -> pos >= node -> len )
1036+ list_del (& node -> q );
1037+ }
1038+ memcpy (out , props -> intermediate , written_bytes );
1039+
1040+ props -> lock .buf_ev_notity -- ;
1041+ pthread_cond_signal (& props -> lock .writable );
1042+ pthread_mutex_unlock (& props -> lock .lock );
1043+ }
1044+
1045+
9991046static int virtio_snd_tx_stream_cb (const void * input ,
10001047 void * output ,
10011048 unsigned long frame_cnt ,
@@ -1030,29 +1077,16 @@ static int virtio_snd_rx_stream_cb(const void *input,
10301077 (void ) time_info ;
10311078 (void ) status_flags ;
10321079
1080+ fprintf (stderr , "rx_stream_cb\n" );
1081+
10331082 vsnd_stream_sel_t * v_ptr = (vsnd_stream_sel_t * ) user_data ;
10341083 uint32_t id = v_ptr -> stream_id ;
10351084 virtio_snd_prop_t * props = & vsnd_props [id ];
10361085 int channels = props -> pp .channels ;
10371086 uint32_t out_buf_sz = frame_cnt * channels ;
10381087 uint32_t out_buf_bytes = out_buf_sz * VSND_CNFA_FRAME_SZ ;
10391088
1040- uint32_t idx = props -> buf_idx ;
1041- uint32_t sz = props -> buf_sz ;
1042- uint32_t base = (idx + out_buf_bytes > sz ) ? (sz - idx ) : out_buf_bytes ;
1043- uint32_t left = out_buf_bytes - base ;
1044- memcpy (props -> intermediate + idx , input , base );
1045- if (left != 0 )
1046- memcpy (props -> intermediate , input + base , left );
1047- props -> buf_idx = (props -> buf_idx + out_buf_bytes ) % sz ;
1048- // enque to list
1049- // FIXME: create cirular queue behavior
1050- __virtio_snd_frame_enqueue (props -> intermediate + idx , out_buf_bytes , id );
1051- fprintf (stderr , "+++ virtio_snd_rx_stream_cb"
1052- " idx %" PRIu32
1053- " base %" PRIu32
1054- " left %" PRIu32 " +++\n" ,
1055- idx , base , left );
1089+ __virtio_snd_rx_frame_enqueue (input , out_buf_bytes , id );
10561090
10571091 return paContinue ;
10581092}
@@ -1149,9 +1183,12 @@ static void __virtio_snd_frame_enqueue(void *payload,
11491183 virtio_snd_prop_t * props = & vsnd_props [stream_id ];
11501184
11511185 pthread_mutex_lock (& props -> lock .lock );
1152- while (props -> lock .buf_ev_notity > 0 )
1186+ while (props -> lock .buf_ev_notity > 0 ) {
1187+ fprintf (stderr , "buf_ev_notity %d" , props -> lock .buf_ev_notity );
11531188 pthread_cond_wait (& props -> lock .writable , & props -> lock .lock );
1189+ }
11541190
1191+ fprintf (stderr , "enque start\n" );
11551192 /* Add a PCM frame to queue */
11561193 /* As stated in Linux Kernel mailing list [1], we keep the pointer
11571194 * points to the payload [2] so that we can always get up-to-date
@@ -1171,8 +1208,60 @@ static void __virtio_snd_frame_enqueue(void *payload,
11711208 list_push (& node -> q , & props -> buf_queue_head );
11721209
11731210 pthread_mutex_unlock (& props -> lock .lock );
1211+ fprintf (stderr , "enque end\n" );
1212+ }
1213+
1214+ // FIXME: create cirular queue behavior
1215+ static void __virtio_snd_rx_frame_enqueue (void * payload ,
1216+ uint32_t n ,
1217+ uint32_t stream_id )
1218+ {
1219+ virtio_snd_prop_t * props = & vsnd_props [stream_id ];
1220+
1221+ pthread_mutex_lock (& props -> lock .lock );
1222+ while (props -> lock .buf_ev_notity > 0 ) {
1223+ fprintf (stderr , "buf_ev_notity %d" , props -> lock .buf_ev_notity );
1224+ pthread_cond_wait (& props -> lock .writable , & props -> lock .lock );
1225+ }
1226+
1227+ fprintf (stderr , "enque start\n" );
1228+
1229+ uint32_t idx = props -> buf_idx ;
1230+ uint32_t sz = props -> buf_sz ;
1231+ uint32_t base = (idx + n > sz ) ? (sz - idx ) : n ;
1232+ uint32_t left = n - base ;
1233+ memcpy (props -> intermediate + idx , payload , base );
1234+ if (left != 0 )
1235+ memcpy (props -> intermediate , payload + base , left );
1236+ props -> buf_idx = (props -> buf_idx + n ) % sz ;
1237+ /* Add a PCM frame to queue */
1238+ /* As stated in Linux Kernel mailing list [1], we keep the pointer
1239+ * points to the payload [2] so that we can always get up-to-date
1240+ * contents of PCM frames.
1241+ * References:
1242+ * [1] https://lore.kernel.org/all/[email protected] /T/ 1243+ * [2]
1244+ * https://github.com/rust-vmm/vhost-device/blob/eb2e2227e41d48a52e4e6346189b772c5363879d/staging/vhost-device-sound/src/device.rs#L554
1245+ */
1246+ /* FIXME: locate the root case of repeating artifact even we
1247+ * keep the pointer of the payload.
1248+ */
1249+ vsnd_buf_queue_node_t * node = malloc (sizeof (* node ));
1250+ node -> addr = props -> intermediate + idx ;
1251+ node -> len = n ;
1252+ node -> pos = 0 ;
1253+ list_push (& node -> q , & props -> buf_queue_head );
1254+
1255+ pthread_mutex_unlock (& props -> lock .lock );
1256+ fprintf (stderr , "enque end\n" );
1257+ fprintf (stderr , "+++ virtio_snd_rx_enqueue"
1258+ " idx %" PRIu32
1259+ " base %" PRIu32
1260+ " left %" PRIu32 " +++\n" ,
1261+ idx , base , left );
11741262}
11751263
1264+
11761265static void virtio_queue_notify_handler (
11771266 virtio_snd_state_t * vsnd ,
11781267 int index ,
0 commit comments