mirror of https://github.com/xemu-project/xemu.git
fixes for 4.0 (audio, usb),
-----BEGIN PGP SIGNATURE----- Version: GnuPG v2.0.22 (GNU/Linux) iQIcBAABAgAGBQJcowU+AAoJEEy22O7T6HE4dLAP/0fvdVi3X+JaYqn3MXI9bmvZ j0zI5VovudwRbHhiBof8Sa+ygX6HI/MuQTmS5hjnRe3yh25g2ISRWVsZ09AXqHdT mHyg3OgMQaCkPXVN8oxRUmRMP6YIpkAA5COG3gT6DTCnuUunF6OWGlLNj929IZe0 U/JLsB6YXhIaQ4UIx0njLih3H7gWlxmrr9O6uJosrAUnHezmOVGjayrGmgCDLNwo FkqzcZlX0X3EXAztnNp0UhLDQ3je3H9XeG/NxNxgDwTElF8MZH5Sa7CgSdV33c+I idFl89twlYBcDqTPeGg2V0pfIelUAL3s+M9dIX9QUvdSIoXmIIw1+/EMsGePMtGC MG+rXC1ff5aRftrIZVuqrRFr2ujrU/8D75MJk/DCFAOBEFrghvMkd3/t3kDlRye7 9sKuVzJu/owY5vaGaI++YJs4Y5/OZqqPfRpWXjHCQKVdVGa4qhHoiYrJQhvnjvqT mENu7C9vW+Rc3dxNAxeimTj8w7Lt9yGwhlRo5X04/IzdxSyUxhlqdrtspZhQr5l9 eLwgvr4898TgNTum2phQtJfrLh3D8peP7/55pIrNu0pgArvEhkZMPsOW4xVDp5N6 Mf5igXnvgLxHqw3q2gJoQN9/LZR/rTzb4vpgERlrhxCo+5VLuioqXZK4A5nfRloW 44uQ1WmNXDxJRWkdkOOi =v7Pc -----END PGP SIGNATURE----- Merge remote-tracking branch 'remotes/kraxel/tags/fixes-20190402-pull-request' into staging fixes for 4.0 (audio, usb), # gpg: Signature made Tue 02 Apr 2019 07:46:22 BST # gpg: using RSA key 4CB6D8EED3E87138 # gpg: Good signature from "Gerd Hoffmann (work) <kraxel@redhat.com>" [full] # gpg: aka "Gerd Hoffmann <gerd@kraxel.org>" [full] # gpg: aka "Gerd Hoffmann (private) <kraxel@gmail.com>" [full] # Primary key fingerprint: A032 8CFF B93A 17A7 9901 FE7D 4CB6 D8EE D3E8 7138 * remotes/kraxel/tags/fixes-20190402-pull-request: audio: fix audio timer rate conversion bug usb-mtp: remove usb_mtp_object_free_one usb-mtp: fix return status of delete hw/usb/bus.c: Handle "no speed matched" case in usb_mask_to_str() Revert "audio: fix pc speaker init" Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
commit
d61d1a1fb2
|
@ -1471,7 +1471,7 @@ static int audio_init(Audiodev *dev)
|
||||||
if (dev->timer_period <= 0) {
|
if (dev->timer_period <= 0) {
|
||||||
s->period_ticks = 1;
|
s->period_ticks = 1;
|
||||||
} else {
|
} else {
|
||||||
s->period_ticks = NANOSECONDS_PER_SECOND / dev->timer_period;
|
s->period_ticks = dev->timer_period * SCALE_US;
|
||||||
}
|
}
|
||||||
|
|
||||||
e = qemu_add_vm_change_state_handler (audio_vm_change_state_handler, s);
|
e = qemu_add_vm_change_state_handler (audio_vm_change_state_handler, s);
|
||||||
|
|
|
@ -26,6 +26,7 @@
|
||||||
#include "audio_int.h"
|
#include "audio_int.h"
|
||||||
#include "qemu-common.h"
|
#include "qemu-common.h"
|
||||||
#include "qemu/cutils.h"
|
#include "qemu/cutils.h"
|
||||||
|
#include "qemu/timer.h"
|
||||||
#include "qapi/error.h"
|
#include "qapi/error.h"
|
||||||
#include "qapi/qapi-visit-audio.h"
|
#include "qapi/qapi-visit-audio.h"
|
||||||
#include "qapi/visitor-impl.h"
|
#include "qapi/visitor-impl.h"
|
||||||
|
@ -338,8 +339,13 @@ static AudiodevListEntry *legacy_opt(const char *drvname)
|
||||||
handle_per_direction(audio_get_pdo_in(e->dev), "QEMU_AUDIO_ADC_");
|
handle_per_direction(audio_get_pdo_in(e->dev), "QEMU_AUDIO_ADC_");
|
||||||
handle_per_direction(audio_get_pdo_out(e->dev), "QEMU_AUDIO_DAC_");
|
handle_per_direction(audio_get_pdo_out(e->dev), "QEMU_AUDIO_DAC_");
|
||||||
|
|
||||||
|
/* Original description: Timer period in HZ (0 - use lowest possible) */
|
||||||
get_int("QEMU_AUDIO_TIMER_PERIOD",
|
get_int("QEMU_AUDIO_TIMER_PERIOD",
|
||||||
&e->dev->timer_period, &e->dev->has_timer_period);
|
&e->dev->timer_period, &e->dev->has_timer_period);
|
||||||
|
if (e->dev->has_timer_period && e->dev->timer_period) {
|
||||||
|
e->dev->timer_period = NANOSECONDS_PER_SECOND / 1000 /
|
||||||
|
e->dev->timer_period;
|
||||||
|
}
|
||||||
|
|
||||||
switch (e->dev->driver) {
|
switch (e->dev->driver) {
|
||||||
case AUDIODEV_DRIVER_ALSA:
|
case AUDIODEV_DRIVER_ALSA:
|
||||||
|
|
|
@ -57,6 +57,7 @@ typedef struct {
|
||||||
} PCSpkState;
|
} PCSpkState;
|
||||||
|
|
||||||
static const char *s_spk = "pcspk";
|
static const char *s_spk = "pcspk";
|
||||||
|
static PCSpkState *pcspk_state;
|
||||||
|
|
||||||
static inline void generate_samples(PCSpkState *s)
|
static inline void generate_samples(PCSpkState *s)
|
||||||
{
|
{
|
||||||
|
@ -110,6 +111,22 @@ static void pcspk_callback(void *opaque, int free)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int pcspk_audio_init(ISABus *bus)
|
||||||
|
{
|
||||||
|
PCSpkState *s = pcspk_state;
|
||||||
|
struct audsettings as = {PCSPK_SAMPLE_RATE, 1, AUDIO_FORMAT_U8, 0};
|
||||||
|
|
||||||
|
AUD_register_card(s_spk, &s->card);
|
||||||
|
|
||||||
|
s->voice = AUD_open_out(&s->card, s->voice, s_spk, s, pcspk_callback, &as);
|
||||||
|
if (!s->voice) {
|
||||||
|
AUD_log(s_spk, "Could not open voice\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static uint64_t pcspk_io_read(void *opaque, hwaddr addr,
|
static uint64_t pcspk_io_read(void *opaque, hwaddr addr,
|
||||||
unsigned size)
|
unsigned size)
|
||||||
{
|
{
|
||||||
|
@ -162,20 +179,12 @@ static void pcspk_initfn(Object *obj)
|
||||||
|
|
||||||
static void pcspk_realizefn(DeviceState *dev, Error **errp)
|
static void pcspk_realizefn(DeviceState *dev, Error **errp)
|
||||||
{
|
{
|
||||||
struct audsettings as = {PCSPK_SAMPLE_RATE, 1, AUDIO_FORMAT_U8, 0};
|
|
||||||
ISADevice *isadev = ISA_DEVICE(dev);
|
ISADevice *isadev = ISA_DEVICE(dev);
|
||||||
PCSpkState *s = PC_SPEAKER(dev);
|
PCSpkState *s = PC_SPEAKER(dev);
|
||||||
|
|
||||||
isa_register_ioport(isadev, &s->ioport, s->iobase);
|
isa_register_ioport(isadev, &s->ioport, s->iobase);
|
||||||
|
|
||||||
AUD_register_card(s_spk, &s->card);
|
pcspk_state = s;
|
||||||
|
|
||||||
s->voice = AUD_open_out(&s->card, s->voice, s_spk, s, pcspk_callback, &as);
|
|
||||||
if (!s->voice) {
|
|
||||||
error_setg(errp, "Initializing audio voice failed");
|
|
||||||
AUD_remove_card(&s->card);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool migrate_needed(void *opaque)
|
static bool migrate_needed(void *opaque)
|
||||||
|
@ -212,6 +221,9 @@ static void pcspk_class_initfn(ObjectClass *klass, void *data)
|
||||||
set_bit(DEVICE_CATEGORY_SOUND, dc->categories);
|
set_bit(DEVICE_CATEGORY_SOUND, dc->categories);
|
||||||
dc->vmsd = &vmstate_spk;
|
dc->vmsd = &vmstate_spk;
|
||||||
dc->props = pcspk_properties;
|
dc->props = pcspk_properties;
|
||||||
|
/* Reason: realize sets global pcspk_state */
|
||||||
|
/* Reason: pit object link */
|
||||||
|
dc->user_creatable = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static const TypeInfo pcspk_info = {
|
static const TypeInfo pcspk_info = {
|
||||||
|
@ -222,12 +234,6 @@ static const TypeInfo pcspk_info = {
|
||||||
.class_init = pcspk_class_initfn,
|
.class_init = pcspk_class_initfn,
|
||||||
};
|
};
|
||||||
|
|
||||||
static int pcspk_audio_init(ISABus *bus)
|
|
||||||
{
|
|
||||||
isa_create_simple(bus, TYPE_PC_SPEAKER);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void pcspk_register(void)
|
static void pcspk_register(void)
|
||||||
{
|
{
|
||||||
type_register_static(&pcspk_info);
|
type_register_static(&pcspk_info);
|
||||||
|
|
|
@ -500,6 +500,10 @@ static void usb_mask_to_str(char *dest, size_t size,
|
||||||
speeds[i].name);
|
speeds[i].name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (pos == 0) {
|
||||||
|
snprintf(dest, size, "unknown");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void usb_check_attach(USBDevice *dev, Error **errp)
|
void usb_check_attach(USBDevice *dev, Error **errp)
|
||||||
|
|
|
@ -1135,28 +1135,25 @@ static MTPData *usb_mtp_get_object_prop_value(MTPState *s, MTPControl *c,
|
||||||
return d;
|
return d;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Return correct return code for a delete event */
|
/*
|
||||||
|
* Return values when object @o is deleted.
|
||||||
|
* If at least one of the deletions succeeded,
|
||||||
|
* DELETE_SUCCESS is set and if at least one
|
||||||
|
* of the deletions failed, DELETE_FAILURE is
|
||||||
|
* set. Both bits being set (DELETE_PARTIAL)
|
||||||
|
* signifies a RES_PARTIAL_DELETE being sent
|
||||||
|
* back to the initiator.
|
||||||
|
*/
|
||||||
enum {
|
enum {
|
||||||
ALL_DELETE,
|
DELETE_SUCCESS = (1 << 0),
|
||||||
PARTIAL_DELETE,
|
DELETE_FAILURE = (1 << 1),
|
||||||
READ_ONLY,
|
DELETE_PARTIAL = (DELETE_FAILURE | DELETE_SUCCESS),
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Assumes that children, if any, have been already freed */
|
|
||||||
static void usb_mtp_object_free_one(MTPState *s, MTPObject *o)
|
|
||||||
{
|
|
||||||
assert(o->nchildren == 0);
|
|
||||||
QTAILQ_REMOVE(&s->objects, o, next);
|
|
||||||
g_free(o->name);
|
|
||||||
g_free(o->path);
|
|
||||||
g_free(o);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int usb_mtp_deletefn(MTPState *s, MTPObject *o, uint32_t trans)
|
static int usb_mtp_deletefn(MTPState *s, MTPObject *o, uint32_t trans)
|
||||||
{
|
{
|
||||||
MTPObject *iter, *iter2;
|
MTPObject *iter, *iter2;
|
||||||
bool partial_delete = false;
|
int ret = 0;
|
||||||
bool success = false;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* TODO: Add support for Protection Status
|
* TODO: Add support for Protection Status
|
||||||
|
@ -1165,34 +1162,28 @@ static int usb_mtp_deletefn(MTPState *s, MTPObject *o, uint32_t trans)
|
||||||
QLIST_FOREACH(iter, &o->children, list) {
|
QLIST_FOREACH(iter, &o->children, list) {
|
||||||
if (iter->format == FMT_ASSOCIATION) {
|
if (iter->format == FMT_ASSOCIATION) {
|
||||||
QLIST_FOREACH(iter2, &iter->children, list) {
|
QLIST_FOREACH(iter2, &iter->children, list) {
|
||||||
usb_mtp_deletefn(s, iter2, trans);
|
ret |= usb_mtp_deletefn(s, iter2, trans);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (o->format == FMT_UNDEFINED_OBJECT) {
|
if (o->format == FMT_UNDEFINED_OBJECT) {
|
||||||
if (remove(o->path)) {
|
if (remove(o->path)) {
|
||||||
partial_delete = true;
|
ret |= DELETE_FAILURE;
|
||||||
} else {
|
} else {
|
||||||
usb_mtp_object_free_one(s, o);
|
usb_mtp_object_free(s, o);
|
||||||
success = true;
|
ret |= DELETE_SUCCESS;
|
||||||
}
|
}
|
||||||
} else if (o->format == FMT_ASSOCIATION) {
|
} else if (o->format == FMT_ASSOCIATION) {
|
||||||
if (rmdir(o->path)) {
|
if (rmdir(o->path)) {
|
||||||
partial_delete = true;
|
ret |= DELETE_FAILURE;
|
||||||
} else {
|
} else {
|
||||||
usb_mtp_object_free_one(s, o);
|
usb_mtp_object_free(s, o);
|
||||||
success = true;
|
ret |= DELETE_SUCCESS;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (success && partial_delete) {
|
return ret;
|
||||||
return PARTIAL_DELETE;
|
|
||||||
}
|
|
||||||
if (!success && partial_delete) {
|
|
||||||
return READ_ONLY;
|
|
||||||
}
|
|
||||||
return ALL_DELETE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void usb_mtp_object_delete(MTPState *s, uint32_t handle,
|
static void usb_mtp_object_delete(MTPState *s, uint32_t handle,
|
||||||
|
@ -1226,19 +1217,24 @@ static void usb_mtp_object_delete(MTPState *s, uint32_t handle,
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = usb_mtp_deletefn(s, o, trans);
|
ret = usb_mtp_deletefn(s, o, trans);
|
||||||
if (ret == PARTIAL_DELETE) {
|
switch (ret) {
|
||||||
usb_mtp_queue_result(s, RES_PARTIAL_DELETE,
|
case DELETE_SUCCESS:
|
||||||
trans, 0, 0, 0, 0);
|
|
||||||
return;
|
|
||||||
} else if (ret == READ_ONLY) {
|
|
||||||
usb_mtp_queue_result(s, RES_STORE_READ_ONLY, trans,
|
|
||||||
0, 0, 0, 0);
|
|
||||||
return;
|
|
||||||
} else {
|
|
||||||
usb_mtp_queue_result(s, RES_OK, trans,
|
usb_mtp_queue_result(s, RES_OK, trans,
|
||||||
0, 0, 0, 0);
|
0, 0, 0, 0);
|
||||||
return;
|
break;
|
||||||
|
case DELETE_FAILURE:
|
||||||
|
usb_mtp_queue_result(s, RES_PARTIAL_DELETE,
|
||||||
|
trans, 0, 0, 0, 0);
|
||||||
|
break;
|
||||||
|
case DELETE_PARTIAL:
|
||||||
|
usb_mtp_queue_result(s, RES_PARTIAL_DELETE,
|
||||||
|
trans, 0, 0, 0, 0);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
g_assert_not_reached();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void usb_mtp_command(MTPState *s, MTPControl *c)
|
static void usb_mtp_command(MTPState *s, MTPControl *c)
|
||||||
|
|
Loading…
Reference in New Issue