From e058fa2dd599ccc780d334558be9c1d155222b80 Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Fri, 3 Jun 2016 11:12:55 +0200 Subject: [PATCH 1/4] usb-host: add special case for bus+addr This patch changes usb-host behavior in case we hostbus= and hostaddr= properties are used to identify the usb device in question. Instead of adding the device to the hotplug watchlist we try to open directly using the given bus number and device address. Putting a device specified by hostaddr to the hotplug watchlist isn't a great idea as the address isn't a fixed property. It changes every time the device is plugged in. So considering this case as "use the device at bus:addr _now_" is more sane. Also usb-host will throw errors in case it can't initialize the host device. Note: For devices on the hotplug watchlist (hostport or vendorid or productid specified) qemu continues to ignore errors and keeps monitoring the usb bus to see if the device eventually shows up. Signed-off-by: Gerd Hoffmann Message-id: 1464945175-28939-1-git-send-email-kraxel@redhat.com --- hw/usb/host-libusb.c | 56 ++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 52 insertions(+), 4 deletions(-) diff --git a/hw/usb/host-libusb.c b/hw/usb/host-libusb.c index 8b774f4939..da59c294bb 100644 --- a/hw/usb/host-libusb.c +++ b/hw/usb/host-libusb.c @@ -81,6 +81,7 @@ struct USBHostDevice { uint32_t iso_urb_frames; uint32_t options; uint32_t loglevel; + bool needs_autoscan; /* state */ QTAILQ_ENTRY(USBHostDevice) next; @@ -974,9 +975,32 @@ static void usb_host_exit_notifier(struct Notifier *n, void *data) } } +static libusb_device *usb_host_find_ref(int bus, int addr) +{ + libusb_device **devs = NULL; + libusb_device *ret = NULL; + int i, n; + + if (usb_host_init() != 0) { + return NULL; + } + n = libusb_get_device_list(ctx, &devs); + for (i = 0; i < n; i++) { + if (libusb_get_bus_number(devs[i]) == bus && + libusb_get_device_address(devs[i]) == addr) { + ret = libusb_ref_device(devs[i]); + break; + } + } + libusb_free_device_list(devs, 1); + return ret; +} + static void usb_host_realize(USBDevice *udev, Error **errp) { USBHostDevice *s = USB_HOST_DEVICE(udev); + libusb_device *ldev; + int rc; if (s->match.vendor_id > 0xffff) { error_setg(errp, "vendorid out of range"); @@ -997,11 +1021,33 @@ static void usb_host_realize(USBDevice *udev, Error **errp) QTAILQ_INIT(&s->requests); QTAILQ_INIT(&s->isorings); + if (s->match.addr && s->match.bus_num && + !s->match.vendor_id && + !s->match.product_id && + !s->match.port) { + s->needs_autoscan = false; + ldev = usb_host_find_ref(s->match.bus_num, + s->match.addr); + if (!ldev) { + error_setg(errp, "failed to find host usb device %d:%d", + s->match.bus_num, s->match.addr); + return; + } + rc = usb_host_open(s, ldev); + libusb_unref_device(ldev); + if (rc < 0) { + error_setg(errp, "failed to open host usb device %d:%d", + s->match.bus_num, s->match.addr); + return; + } + } else { + s->needs_autoscan = true; + QTAILQ_INSERT_TAIL(&hostdevs, s, next); + usb_host_auto_check(NULL); + } + s->exit.notify = usb_host_exit_notifier; qemu_add_exit_notifier(&s->exit); - - QTAILQ_INSERT_TAIL(&hostdevs, s, next); - usb_host_auto_check(NULL); } static void usb_host_instance_init(Object *obj) @@ -1019,7 +1065,9 @@ static void usb_host_handle_destroy(USBDevice *udev) USBHostDevice *s = USB_HOST_DEVICE(udev); qemu_remove_exit_notifier(&s->exit); - QTAILQ_REMOVE(&hostdevs, s, next); + if (s->needs_autoscan) { + QTAILQ_REMOVE(&hostdevs, s, next); + } usb_host_close(s); } From ec9125bc0ef39bca89854df1bf568c78bf84050d Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Fri, 10 Jun 2016 16:37:57 +0100 Subject: [PATCH 2/4] hw/usb/dev-network.c: Use ldl_le_p() and stl_le_p() Use stl_le_p() and ldl_le_p() to read and write data from buffers, rather than using pointer casts and cpu_to_le32() for writes and le32_to_cpup() for reads. This: * avoids lots of casts * works even if the buffer isn't as aligned as the host would like * avoids using the *_to_cpup() functions which we want to get rid of Note that there may still be some places where a pointer from the guest is cast to a pointer to a host structure; these would also have to be changed for the device to work on a host CPU which enforces alignment restrictions. Signed-off-by: Peter Maydell Reviewed-by: Eric Blake Message-id: 1465573077-29221-1-git-send-email-peter.maydell@linaro.org Signed-off-by: Gerd Hoffmann --- hw/usb/dev-network.c | 63 +++++++++++++++++++++----------------------- 1 file changed, 30 insertions(+), 33 deletions(-) diff --git a/hw/usb/dev-network.c b/hw/usb/dev-network.c index 74306b58e3..5c18198f55 100644 --- a/hw/usb/dev-network.c +++ b/hw/usb/dev-network.c @@ -670,48 +670,49 @@ static int ndis_query(USBNetState *s, uint32_t oid, /* general oids (table 4-1) */ /* mandatory */ case OID_GEN_SUPPORTED_LIST: - for (i = 0; i < ARRAY_SIZE(oid_supported_list); i++) - ((le32 *) outbuf)[i] = cpu_to_le32(oid_supported_list[i]); + for (i = 0; i < ARRAY_SIZE(oid_supported_list); i++) { + stl_le_p(outbuf + (i * sizeof(le32)), oid_supported_list[i]); + } return sizeof(oid_supported_list); /* mandatory */ case OID_GEN_HARDWARE_STATUS: - *((le32 *) outbuf) = cpu_to_le32(0); + stl_le_p(outbuf, 0); return sizeof(le32); /* mandatory */ case OID_GEN_MEDIA_SUPPORTED: - *((le32 *) outbuf) = cpu_to_le32(s->medium); + stl_le_p(outbuf, s->medium); return sizeof(le32); /* mandatory */ case OID_GEN_MEDIA_IN_USE: - *((le32 *) outbuf) = cpu_to_le32(s->medium); + stl_le_p(outbuf, s->medium); return sizeof(le32); /* mandatory */ case OID_GEN_MAXIMUM_FRAME_SIZE: - *((le32 *) outbuf) = cpu_to_le32(ETH_FRAME_LEN); + stl_le_p(outbuf, ETH_FRAME_LEN); return sizeof(le32); /* mandatory */ case OID_GEN_LINK_SPEED: - *((le32 *) outbuf) = cpu_to_le32(s->speed); + stl_le_p(outbuf, s->speed); return sizeof(le32); /* mandatory */ case OID_GEN_TRANSMIT_BLOCK_SIZE: - *((le32 *) outbuf) = cpu_to_le32(ETH_FRAME_LEN); + stl_le_p(outbuf, ETH_FRAME_LEN); return sizeof(le32); /* mandatory */ case OID_GEN_RECEIVE_BLOCK_SIZE: - *((le32 *) outbuf) = cpu_to_le32(ETH_FRAME_LEN); + stl_le_p(outbuf, ETH_FRAME_LEN); return sizeof(le32); /* mandatory */ case OID_GEN_VENDOR_ID: - *((le32 *) outbuf) = cpu_to_le32(s->vendorid); + stl_le_p(outbuf, s->vendorid); return sizeof(le32); /* mandatory */ @@ -720,58 +721,57 @@ static int ndis_query(USBNetState *s, uint32_t oid, return strlen((char *)outbuf) + 1; case OID_GEN_VENDOR_DRIVER_VERSION: - *((le32 *) outbuf) = cpu_to_le32(1); + stl_le_p(outbuf, 1); return sizeof(le32); /* mandatory */ case OID_GEN_CURRENT_PACKET_FILTER: - *((le32 *) outbuf) = cpu_to_le32(s->filter); + stl_le_p(outbuf, s->filter); return sizeof(le32); /* mandatory */ case OID_GEN_MAXIMUM_TOTAL_SIZE: - *((le32 *) outbuf) = cpu_to_le32(RNDIS_MAX_TOTAL_SIZE); + stl_le_p(outbuf, RNDIS_MAX_TOTAL_SIZE); return sizeof(le32); /* mandatory */ case OID_GEN_MEDIA_CONNECT_STATUS: - *((le32 *) outbuf) = cpu_to_le32(s->media_state); + stl_le_p(outbuf, s->media_state); return sizeof(le32); case OID_GEN_PHYSICAL_MEDIUM: - *((le32 *) outbuf) = cpu_to_le32(0); + stl_le_p(outbuf, 0); return sizeof(le32); case OID_GEN_MAC_OPTIONS: - *((le32 *) outbuf) = cpu_to_le32( - NDIS_MAC_OPTION_RECEIVE_SERIALIZED | - NDIS_MAC_OPTION_FULL_DUPLEX); + stl_le_p(outbuf, NDIS_MAC_OPTION_RECEIVE_SERIALIZED | + NDIS_MAC_OPTION_FULL_DUPLEX); return sizeof(le32); /* statistics OIDs (table 4-2) */ /* mandatory */ case OID_GEN_XMIT_OK: - *((le32 *) outbuf) = cpu_to_le32(0); + stl_le_p(outbuf, 0); return sizeof(le32); /* mandatory */ case OID_GEN_RCV_OK: - *((le32 *) outbuf) = cpu_to_le32(0); + stl_le_p(outbuf, 0); return sizeof(le32); /* mandatory */ case OID_GEN_XMIT_ERROR: - *((le32 *) outbuf) = cpu_to_le32(0); + stl_le_p(outbuf, 0); return sizeof(le32); /* mandatory */ case OID_GEN_RCV_ERROR: - *((le32 *) outbuf) = cpu_to_le32(0); + stl_le_p(outbuf, 0); return sizeof(le32); /* mandatory */ case OID_GEN_RCV_NO_BUFFER: - *((le32 *) outbuf) = cpu_to_le32(0); + stl_le_p(outbuf, 0); return sizeof(le32); /* ieee802.3 OIDs (table 4-3) */ @@ -787,12 +787,12 @@ static int ndis_query(USBNetState *s, uint32_t oid, /* mandatory */ case OID_802_3_MULTICAST_LIST: - *((le32 *) outbuf) = cpu_to_le32(0xe0000000); + stl_le_p(outbuf, 0xe0000000); return sizeof(le32); /* mandatory */ case OID_802_3_MAXIMUM_LIST_SIZE: - *((le32 *) outbuf) = cpu_to_le32(1); + stl_le_p(outbuf, 1); return sizeof(le32); case OID_802_3_MAC_OPTIONS: @@ -801,17 +801,17 @@ static int ndis_query(USBNetState *s, uint32_t oid, /* ieee802.3 statistics OIDs (table 4-4) */ /* mandatory */ case OID_802_3_RCV_ERROR_ALIGNMENT: - *((le32 *) outbuf) = cpu_to_le32(0); + stl_le_p(outbuf, 0); return sizeof(le32); /* mandatory */ case OID_802_3_XMIT_ONE_COLLISION: - *((le32 *) outbuf) = cpu_to_le32(0); + stl_le_p(outbuf, 0); return sizeof(le32); /* mandatory */ case OID_802_3_XMIT_MORE_COLLISIONS: - *((le32 *) outbuf) = cpu_to_le32(0); + stl_le_p(outbuf, 0); return sizeof(le32); default: @@ -826,7 +826,7 @@ static int ndis_set(USBNetState *s, uint32_t oid, { switch (oid) { case OID_GEN_CURRENT_PACKET_FILTER: - s->filter = le32_to_cpup((le32 *) inbuf); + s->filter = ldl_le_p(inbuf); if (s->filter) { s->rndis_state = RNDIS_DATA_INITIALIZED; } else { @@ -1026,10 +1026,7 @@ static void usb_net_reset_in_buf(USBNetState *s) static int rndis_parse(USBNetState *s, uint8_t *data, int length) { - uint32_t msg_type; - le32 *tmp = (le32 *) data; - - msg_type = le32_to_cpup(tmp); + uint32_t msg_type = ldl_le_p(data); switch (msg_type) { case RNDIS_INITIALIZE_MSG: From c92cfba822245c42fec611f310ed74c1821be3d2 Mon Sep 17 00:00:00 2001 From: Eduardo Habkost Date: Wed, 8 Jun 2016 17:50:24 -0300 Subject: [PATCH 3/4] pxa2xx: Unconditionally enable USB controller Simplify initialization logic by removing the usb_enabled() check. The USB controller is part of the SoC, so it doesn't make sense to create a system where it is not present. Cc: Peter Maydell Cc: Andrzej Zaborowski Cc: qemu-arm@nongnu.org, Signed-off-by: Eduardo Habkost Reviewed-by: Peter Maydell Message-id: 1465419025-21519-2-git-send-email-ehabkost@redhat.com Signed-off-by: Gerd Hoffmann --- hw/arm/pxa2xx.c | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/hw/arm/pxa2xx.c b/hw/arm/pxa2xx.c index e41a7c92ab..cb55704687 100644 --- a/hw/arm/pxa2xx.c +++ b/hw/arm/pxa2xx.c @@ -2165,10 +2165,8 @@ PXA2xxState *pxa270_init(MemoryRegion *address_space, s->ssp[i] = (SSIBus *)qdev_get_child_bus(dev, "ssi"); } - if (usb_enabled()) { - sysbus_create_simple("sysbus-ohci", 0x4c000000, - qdev_get_gpio_in(s->pic, PXA2XX_PIC_USBH1)); - } + sysbus_create_simple("sysbus-ohci", 0x4c000000, + qdev_get_gpio_in(s->pic, PXA2XX_PIC_USBH1)); s->pcmcia[0] = pxa2xx_pcmcia_init(address_space, 0x20000000); s->pcmcia[1] = pxa2xx_pcmcia_init(address_space, 0x30000000); @@ -2298,10 +2296,8 @@ PXA2xxState *pxa255_init(MemoryRegion *address_space, unsigned int sdram_size) s->ssp[i] = (SSIBus *)qdev_get_child_bus(dev, "ssi"); } - if (usb_enabled()) { - sysbus_create_simple("sysbus-ohci", 0x4c000000, - qdev_get_gpio_in(s->pic, PXA2XX_PIC_USBH1)); - } + sysbus_create_simple("sysbus-ohci", 0x4c000000, + qdev_get_gpio_in(s->pic, PXA2XX_PIC_USBH1)); s->pcmcia[0] = pxa2xx_pcmcia_init(address_space, 0x20000000); s->pcmcia[1] = pxa2xx_pcmcia_init(address_space, 0x30000000); From 4bcbe0b63661b1df8e78d58270574d818b387d2c Mon Sep 17 00:00:00 2001 From: Eduardo Habkost Date: Wed, 8 Jun 2016 17:50:25 -0300 Subject: [PATCH 4/4] vl: Eliminate usb_enabled() This wrapper for machine_usb(current_machine) is not necessary, replace all usages of usb_enabled() with machine_usb(). Cc: Peter Maydell Cc: "Michael S. Tsirkin" Cc: Alexander Graf Cc: qemu-arm@nongnu.org Cc: qemu-ppc@nongnu.org Signed-off-by: Eduardo Habkost Reviewed-by: Marcel Apfelbaum Reviewed-by: Thomas Huth Message-id: 1465419025-21519-3-git-send-email-ehabkost@redhat.com Signed-off-by: Gerd Hoffmann --- hw/arm/nseries.c | 2 +- hw/arm/realview.c | 2 +- hw/arm/versatilepb.c | 2 +- hw/i386/pc_piix.c | 2 +- hw/i386/pc_q35.c | 2 +- hw/ppc/mac_oldworld.c | 2 +- hw/ppc/prep.c | 2 +- include/sysemu/sysemu.h | 1 - vl.c | 11 +++-------- 9 files changed, 10 insertions(+), 16 deletions(-) diff --git a/hw/arm/nseries.c b/hw/arm/nseries.c index d4eb141764..fea911e3e3 100644 --- a/hw/arm/nseries.c +++ b/hw/arm/nseries.c @@ -1351,7 +1351,7 @@ static void n8x0_init(MachineState *machine, n8x0_dss_setup(s); n8x0_cbus_setup(s); n8x0_uart_setup(s); - if (usb_enabled()) { + if (machine_usb(machine)) { n8x0_usb_setup(s); } diff --git a/hw/arm/realview.c b/hw/arm/realview.c index 7d0aa6ff4f..8eafccaf1d 100644 --- a/hw/arm/realview.c +++ b/hw/arm/realview.c @@ -254,7 +254,7 @@ static void realview_init(MachineState *machine, sysbus_connect_irq(busdev, 2, pic[50]); sysbus_connect_irq(busdev, 3, pic[51]); pci_bus = (PCIBus *)qdev_get_child_bus(dev, "pci"); - if (usb_enabled()) { + if (machine_usb(machine)) { pci_create_simple(pci_bus, -1, "pci-ohci"); } n = drive_get_max_bus(IF_SCSI); diff --git a/hw/arm/versatilepb.c b/hw/arm/versatilepb.c index 20dd3561c8..8ae5392bcc 100644 --- a/hw/arm/versatilepb.c +++ b/hw/arm/versatilepb.c @@ -276,7 +276,7 @@ static void versatile_init(MachineState *machine, int board_id) pci_nic_init_nofail(nd, pci_bus, "rtl8139", NULL); } } - if (usb_enabled()) { + if (machine_usb(machine)) { pci_create_simple(pci_bus, -1, "pci-ohci"); } n = drive_get_max_bus(IF_SCSI); diff --git a/hw/i386/pc_piix.c b/hw/i386/pc_piix.c index 14dd0cc774..82c7c0a5fa 100644 --- a/hw/i386/pc_piix.c +++ b/hw/i386/pc_piix.c @@ -262,7 +262,7 @@ static void pc_init1(MachineState *machine, pc_cmos_init(pcms, idebus[0], idebus[1], rtc_state); - if (pcmc->pci_enabled && usb_enabled()) { + if (pcmc->pci_enabled && machine_usb(machine)) { pci_create_simple(pci_bus, piix3_devfn + 2, "piix3-usb-uhci"); } diff --git a/hw/i386/pc_q35.c b/hw/i386/pc_q35.c index 04aae8958c..31a6a59383 100644 --- a/hw/i386/pc_q35.c +++ b/hw/i386/pc_q35.c @@ -234,7 +234,7 @@ static void pc_q35_init(MachineState *machine) ide_drive_get(hd, ICH_AHCI(ahci)->ahci.ports); ahci_ide_create_devs(ahci, hd); - if (usb_enabled()) { + if (machine_usb(machine)) { /* Should we create 6 UHCI according to ich9 spec? */ ehci_create_ich9_with_companions(host_bus, 0x1d); } diff --git a/hw/ppc/mac_oldworld.c b/hw/ppc/mac_oldworld.c index a9bb1c27df..447948746b 100644 --- a/hw/ppc/mac_oldworld.c +++ b/hw/ppc/mac_oldworld.c @@ -309,7 +309,7 @@ static void ppc_heathrow_init(MachineState *machine) dev = qdev_create(adb_bus, TYPE_ADB_MOUSE); qdev_init_nofail(dev); - if (usb_enabled()) { + if (machine_usb(machine)) { pci_create_simple(pci_bus, -1, "pci-ohci"); } diff --git a/hw/ppc/prep.c b/hw/ppc/prep.c index 07ffe72de1..054af1e8b4 100644 --- a/hw/ppc/prep.c +++ b/hw/ppc/prep.c @@ -649,7 +649,7 @@ static void ppc_prep_init(MachineState *machine) memory_region_add_subregion(sysmem, 0xFEFF0000, xcsr); #endif - if (usb_enabled()) { + if (machine_usb(machine)) { pci_create_simple(pci_bus, -1, "pci-ohci"); } diff --git a/include/sysemu/sysemu.h b/include/sysemu/sysemu.h index 94281413d0..7313673b66 100644 --- a/include/sysemu/sysemu.h +++ b/include/sysemu/sysemu.h @@ -233,7 +233,6 @@ void qemu_boot_set(const char *boot_order, Error **errp); QemuOpts *qemu_get_machine_opts(void); bool defaults_enabled(void); -bool usb_enabled(void); extern QemuOptsList qemu_legacy_drive_opts; extern QemuOptsList qemu_common_drive_opts; diff --git a/vl.c b/vl.c index b0bcc255ee..45eff5661b 100644 --- a/vl.c +++ b/vl.c @@ -1072,11 +1072,6 @@ bool defaults_enabled(void) return has_defaults; } -bool usb_enabled(void) -{ - return machine_usb(current_machine); -} - #ifndef _WIN32 static int parse_add_fd(void *opaque, QemuOpts *opts, Error **errp) { @@ -1393,7 +1388,7 @@ static int usb_device_add(const char *devname) const char *p; #endif - if (!usb_enabled()) { + if (!machine_usb(current_machine)) { return -1; } @@ -1425,7 +1420,7 @@ static int usb_device_del(const char *devname) return -1; } - if (!usb_enabled()) { + if (!machine_usb(current_machine)) { return -1; } @@ -4501,7 +4496,7 @@ int main(int argc, char **argv, char **envp) } /* init USB devices */ - if (usb_enabled()) { + if (machine_usb(current_machine)) { if (foreach_device_config(DEV_USB, usb_parse) < 0) exit(1); }