Commit d61d1a1f authored by Peter Maydell's avatar Peter Maydell
Browse files

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: default avatarPeter Maydell <peter.maydell@linaro.org>
parents 47175951 be1092af
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -1471,7 +1471,7 @@ static int audio_init(Audiodev *dev)
    if (dev->timer_period <= 0) {
        s->period_ticks = 1;
    } 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);
+6 −0
Original line number Diff line number Diff line
@@ -26,6 +26,7 @@
#include "audio_int.h"
#include "qemu-common.h"
#include "qemu/cutils.h"
#include "qemu/timer.h"
#include "qapi/error.h"
#include "qapi/qapi-visit-audio.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_out(e->dev), "QEMU_AUDIO_DAC_");

    /* Original description: Timer period in HZ (0 - use lowest possible) */
    get_int("QEMU_AUDIO_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) {
    case AUDIODEV_DRIVER_ALSA:
+21 −15
Original line number Diff line number Diff line
@@ -57,6 +57,7 @@ typedef struct {
} PCSpkState;

static const char *s_spk = "pcspk";
static PCSpkState *pcspk_state;

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,
                              unsigned size)
{
@@ -162,20 +179,12 @@ static void pcspk_initfn(Object *obj)

static void pcspk_realizefn(DeviceState *dev, Error **errp)
{
    struct audsettings as = {PCSPK_SAMPLE_RATE, 1, AUDIO_FORMAT_U8, 0};
    ISADevice *isadev = ISA_DEVICE(dev);
    PCSpkState *s = PC_SPEAKER(dev);

    isa_register_ioport(isadev, &s->ioport, s->iobase);

    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) {
        error_setg(errp, "Initializing audio voice failed");
        AUD_remove_card(&s->card);
        return;
    }
    pcspk_state = s;
}

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);
    dc->vmsd = &vmstate_spk;
    dc->props = pcspk_properties;
    /* Reason: realize sets global pcspk_state */
    /* Reason: pit object link */
    dc->user_creatable = false;
}

static const TypeInfo pcspk_info = {
@@ -222,12 +234,6 @@ static const TypeInfo pcspk_info = {
    .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)
{
    type_register_static(&pcspk_info);
+4 −0
Original line number Diff line number Diff line
@@ -500,6 +500,10 @@ static void usb_mask_to_str(char *dest, size_t size,
                            speeds[i].name);
        }
    }

    if (pos == 0) {
        snprintf(dest, size, "unknown");
    }
}

void usb_check_attach(USBDevice *dev, Error **errp)
+36 −40
Original line number Diff line number Diff line
@@ -1135,28 +1135,25 @@ static MTPData *usb_mtp_get_object_prop_value(MTPState *s, MTPControl *c,
    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 {
    ALL_DELETE,
    PARTIAL_DELETE,
    READ_ONLY,
    DELETE_SUCCESS = (1 << 0),
    DELETE_FAILURE = (1 << 1),
    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)
{
    MTPObject *iter, *iter2;
    bool partial_delete = false;
    bool success = false;
    int ret = 0;

    /*
     * 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) {
        if (iter->format == FMT_ASSOCIATION) {
            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 (remove(o->path)) {
            partial_delete = true;
            ret |= DELETE_FAILURE;
        } else {
            usb_mtp_object_free_one(s, o);
            success = true;
            usb_mtp_object_free(s, o);
            ret |= DELETE_SUCCESS;
        }
    } else if (o->format == FMT_ASSOCIATION) {
        if (rmdir(o->path)) {
            partial_delete = true;
            ret |= DELETE_FAILURE;
        } else {
            usb_mtp_object_free_one(s, o);
            success = true;
            usb_mtp_object_free(s, o);
            ret |= DELETE_SUCCESS;
        }
    }

    if (success && partial_delete) {
        return PARTIAL_DELETE;
    }
    if (!success && partial_delete) {
        return READ_ONLY;
    }
    return ALL_DELETE;
    return ret;
}

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);
    if (ret == PARTIAL_DELETE) {
        usb_mtp_queue_result(s, RES_PARTIAL_DELETE,
                             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 {
    switch (ret) {
    case DELETE_SUCCESS:
        usb_mtp_queue_result(s, RES_OK, trans,
                             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)