symbian-qemu-0.9.1-12/qemu-symbian-svp/hw/virtio-audio.c
changeset 72 d00bf4f57250
parent 1 2fb8b9db1c86
--- a/symbian-qemu-0.9.1-12/qemu-symbian-svp/hw/virtio-audio.c	Mon May 10 11:37:38 2010 +0100
+++ b/symbian-qemu-0.9.1-12/qemu-symbian-svp/hw/virtio-audio.c	Wed May 12 23:13:16 2010 +0100
@@ -39,6 +39,9 @@
 
 #define NUM_STREAMS 2
 
+#define VIRT_CONTROL_QUEUE_SIZE 0x40
+#define VIRT_DATA_QUEUE_SIZE 0x80
+
 typedef struct {
     struct VirtIOAudio *dev;
     VirtQueue *data_vq;
@@ -97,9 +100,13 @@
     if (stream->in_voice) {
         iov_len = stream->elem.in_num;
         iov = stream->elem.in_sg;
-    } else {
+    } else if (stream->out_voice) {
         iov_len = stream->elem.out_num;
         iov = stream->elem.out_sg;
+    } else
+    {
+        DPRINTF("No voice selected skipping block\n");
+        return 0;
     }
     written = 0;
     for (n = 0; total_len > 0 && n < iov_len; n++) {
@@ -119,8 +126,10 @@
         while (to_write) {
             if (stream->in_voice) {
                 size = AUD_read(stream->in_voice, p, to_write);
+            } else if (stream->out_voice) {
+                size = AUD_write(stream->out_voice, p, to_write);
             } else {
-                size = AUD_write(stream->out_voice, p, to_write);
+                size = 0;
             }
             DPRINTF("Copied %d/%d\n", size, to_write);
             if (size == 0) {
@@ -141,10 +150,14 @@
     int n;
 
     DPRINTF("Callback (%d)\n", avail);
+    if ((!stream->in_voice)&&(!stream->out_voice))
+    {
+        DPRINTF("Skipping callback as no voice is selected!\n");
+    }
     while (avail) {
         while (stream->data_left == 0) {
             if (stream->has_buffer) {
-                virtqueue_push(stream->data_vq, &stream->elem, 0);
+                virtqueue_push(stream->data_vq, &stream->elem, stream->data_offset);
                 virtio_notify(&stream->dev->vdev, stream->data_vq);
                 stream->has_buffer = 0;
             }
@@ -160,7 +173,7 @@
             if (stream->in_voice) {
                 for (n = 0; n < stream->elem.in_num; n++)
                     stream->data_left += stream->elem.in_sg[n].iov_len;
-            } else {
+            } else if (stream->out_voice) {
                 for (n = 0; n < stream->elem.out_num; n++)
                     stream->data_left += stream->elem.out_sg[n].iov_len;
             }
@@ -175,7 +188,7 @@
             break;
     }
     if (stream->data_left == 0 && stream->has_buffer) {
-        virtqueue_push(stream->data_vq, &stream->elem, 0);
+        virtqueue_push(stream->data_vq, &stream->elem, stream->data_offset);
         virtio_notify(&stream->dev->vdev, stream->data_vq);
         stream->has_buffer = 0;
     }
@@ -220,6 +233,7 @@
     uint32_t value;
 
     while (virtqueue_pop(s->cmd_vq, &elem)) {
+        size_t bytes_transferred = 0;
         for (out_n = 0; out_n < elem.out_num; out_n++) {
             p = (uint32_t *)elem.out_sg[out_n].iov_base;
             len = elem.out_sg[out_n].iov_len;
@@ -249,7 +263,8 @@
                     stream->fmt.freq = value;
                     break;
                 case VIRTIO_AUDIO_CMD_INIT:
-                    if (value & 1) {
+                    out_bytes = 0;
+                    if (value == 1) {
                         if (stream->out_voice) {
                             AUD_close_out(&s->card, stream->out_voice);
                             stream->out_voice = NULL;
@@ -261,8 +276,8 @@
                                       virtio_audio_callback,
                                       &stream->fmt);
                         virtio_audio_cmd_result(0, &elem, &out_bytes);
-                    } else {
-                        if (stream->out_voice) {
+                    } else if (value == 0) {
+                        if (stream->in_voice) {
                             AUD_close_in(&s->card, stream->in_voice);
                             stream->in_voice = NULL;
                         }
@@ -274,21 +289,36 @@
                                        &stream->fmt);
                         value = AUD_get_buffer_size_out(stream->out_voice);
                         virtio_audio_cmd_result(value, &elem, &out_bytes);
+                    } else { // let us close all down
+                        if (stream->out_voice) {
+                            AUD_close_out(&s->card, stream->out_voice);
+                            stream->out_voice = NULL;
+                        }
+                        if (stream->in_voice) {
+                            AUD_close_in(&s->card, stream->in_voice);
+                            stream->in_voice = NULL;
+                        }                        
                     }
+                    bytes_transferred += out_bytes;
                     break;
                 case VIRTIO_AUDIO_CMD_RUN:
                     if (stream->in_voice) {
                         AUD_set_active_in(stream->in_voice, value);
-                    } else {
+                    } else if (stream->out_voice) {
                         AUD_set_active_out(stream->out_voice, value);
+                    } else
+                    {
+                        DPRINTF("Cannot execute CMD_RUN as no voice is active\n");
                     }
                     break;
                 }
                 p += 3;
                 len -= 12;
+                bytes_transferred += 12;
             }
         }
-        virtqueue_push(s->cmd_vq, &elem, out_bytes);
+        virtqueue_push(s->cmd_vq, &elem, bytes_transferred);
+        virtio_notify(vdev, s->cmd_vq);		
     }
 }
 
@@ -314,7 +344,7 @@
             if (AUD_is_active_in(stream->in_voice))
                 mode |= 1;
         } else if (stream->out_voice) {
-            mode |= 4;
+            mode = 4;
             if (AUD_is_active_out(stream->out_voice))
                 mode |= 1;
         } else {
@@ -394,9 +424,9 @@
     s->vdev.get_config = virtio_audio_get_config;
     s->vdev.get_features = virtio_audio_get_features;
     s->vdev.set_features = virtio_audio_set_features;
-    s->cmd_vq = virtio_add_queue(&s->vdev, 64, virtio_audio_handle_cmd);
+    s->cmd_vq = virtio_add_queue(&s->vdev, VIRT_CONTROL_QUEUE_SIZE, virtio_audio_handle_cmd);
     for (i = 0; i < NUM_STREAMS; i++) {
-        s->stream[i].data_vq = virtio_add_queue(&s->vdev, 128,
+        s->stream[i].data_vq = virtio_add_queue(&s->vdev, VIRT_DATA_QUEUE_SIZE,
                                                 virtio_audio_handle_data);
         s->stream[i].dev = s;
     }