diff -r 5158c0d3bde3 -r d00bf4f57250 symbian-qemu-0.9.1-12/qemu-symbian-svp/hw/virtio-audio.c --- 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; }