diff options
Diffstat (limited to 'hw')
-rw-r--r-- | hw/bt-hid.c | 3 | ||||
-rw-r--r-- | hw/usb-bus.c | 140 | ||||
-rw-r--r-- | hw/usb-hid.c | 15 | ||||
-rw-r--r-- | hw/usb-hub.c | 8 | ||||
-rw-r--r-- | hw/usb-musb.c | 4 | ||||
-rw-r--r-- | hw/usb-ohci.c | 4 | ||||
-rw-r--r-- | hw/usb-uhci.c | 7 | ||||
-rw-r--r-- | hw/usb-wacom.c | 5 | ||||
-rw-r--r-- | hw/usb.h | 28 |
9 files changed, 164 insertions, 50 deletions
diff --git a/hw/bt-hid.c b/hw/bt-hid.c index 6f37705494..020176eacc 100644 --- a/hw/bt-hid.c +++ b/hw/bt-hid.c @@ -566,5 +566,6 @@ static struct bt_device_s *bt_hid_init(struct bt_scatternet_s *net, struct bt_device_s *bt_keyboard_init(struct bt_scatternet_s *net) { - return bt_hid_init(net, usb_keyboard_init(), class_keyboard); + USBDevice *dev = usb_create_simple(NULL /* FIXME */, "QEMU USB Keyboard"); + return bt_hid_init(net, dev, class_keyboard); } diff --git a/hw/usb-bus.c b/hw/usb-bus.c index c695a379cd..169fb2f58d 100644 --- a/hw/usb-bus.c +++ b/hw/usb-bus.c @@ -1,10 +1,15 @@ #include "hw.h" #include "usb.h" #include "qdev.h" +#include "sysemu.h" +#include "monitor.h" + +static void usb_bus_dev_print(Monitor *mon, DeviceState *qdev, int indent); static struct BusInfo usb_bus_info = { - .name = "USB", - .size = sizeof(USBBus), + .name = "USB", + .size = sizeof(USBBus), + .print_dev = usb_bus_dev_print, }; static int next_usb_bus = 0; static TAILQ_HEAD(, USBBus) busses = TAILQ_HEAD_INITIALIZER(busses); @@ -43,6 +48,8 @@ static int usb_qdev_init(DeviceState *qdev, DeviceInfo *base) pstrcpy(dev->devname, sizeof(dev->devname), qdev->info->name); dev->info = info; rc = dev->info->init(dev); + if (rc == 0) + usb_device_attach(dev); return rc; } @@ -61,7 +68,7 @@ void usb_qdev_register_many(USBDeviceInfo *info) } } -USBDevice *usb_create_simple(USBBus *bus, const char *name) +USBDevice *usb_create(USBBus *bus, const char *name) { DeviceState *dev; @@ -77,6 +84,131 @@ USBDevice *usb_create_simple(USBBus *bus, const char *name) #endif dev = qdev_create(&bus->qbus, name); - qdev_init(dev); return DO_UPCAST(USBDevice, qdev, dev); } + +USBDevice *usb_create_simple(USBBus *bus, const char *name) +{ + USBDevice *dev = usb_create(bus, name); + qdev_init(&dev->qdev); + return dev; +} + +void usb_register_port(USBBus *bus, USBPort *port, void *opaque, int index, + usb_attachfn attach) +{ + port->opaque = opaque; + port->index = index; + port->attach = attach; + TAILQ_INSERT_TAIL(&bus->free, port, next); + bus->nfree++; +} + +static void do_attach(USBDevice *dev) +{ + USBBus *bus = usb_bus_from_device(dev); + USBPort *port; + + if (dev->attached) { + fprintf(stderr, "Warning: tried to attach usb device %s twice\n", + dev->devname); + return; + } + dev->attached++; + + port = TAILQ_FIRST(&bus->free); + TAILQ_REMOVE(&bus->free, port, next); + bus->nfree--; + + usb_attach(port, dev); + + TAILQ_INSERT_TAIL(&bus->used, port, next); + bus->nused++; +} + +int usb_device_attach(USBDevice *dev) +{ + USBBus *bus = usb_bus_from_device(dev); + USBDevice *hub; + + if (bus->nfree == 1) { + /* Create a new hub and chain it on. */ + hub = usb_create_simple(bus, "QEMU USB Hub"); + } + do_attach(dev); + return 0; +} + +int usb_device_delete_addr(int busnr, int addr) +{ + USBBus *bus; + USBPort *port; + USBDevice *dev; + + bus = usb_bus_find(busnr); + if (!bus) + return -1; + + TAILQ_FOREACH(port, &bus->used, next) { + if (port->dev->addr == addr) + break; + } + if (!port) + return -1; + + dev = port->dev; + TAILQ_REMOVE(&bus->used, port, next); + bus->nused--; + + usb_attach(port, NULL); + dev->info->handle_destroy(dev); + + TAILQ_INSERT_TAIL(&bus->free, port, next); + bus->nfree++; + return 0; +} + +static const char *usb_speed(unsigned int speed) +{ + static const char *txt[] = { + [ USB_SPEED_LOW ] = "1.5", + [ USB_SPEED_FULL ] = "12", + [ USB_SPEED_HIGH ] = "480", + }; + if (speed >= ARRAY_SIZE(txt)) + return "?"; + return txt[speed]; +} + +static void usb_bus_dev_print(Monitor *mon, DeviceState *qdev, int indent) +{ + USBDevice *dev = DO_UPCAST(USBDevice, qdev, qdev); + USBBus *bus = usb_bus_from_device(dev); + + monitor_printf(mon, "%*saddr %d.%d, speed %s, name %s\n", indent, "", + bus->busnr, dev->addr, + usb_speed(dev->speed), dev->devname); +} + +void usb_info(Monitor *mon) +{ + USBBus *bus; + USBDevice *dev; + USBPort *port; + + if (TAILQ_EMPTY(&busses)) { + monitor_printf(mon, "USB support not enabled\n"); + return; + } + + TAILQ_FOREACH(bus, &busses, next) { + TAILQ_FOREACH(port, &bus->used, next) { + dev = port->dev; + if (!dev) + continue; + monitor_printf(mon, " Device %d.%d, Speed %s Mb/s, Product %s\n", + bus->busnr, dev->addr, usb_speed(dev->speed), dev->devname); + } + } +} + diff --git a/hw/usb-hid.c b/hw/usb-hid.c index c8b6ee7cd1..0837ec1587 100644 --- a/hw/usb-hid.c +++ b/hw/usb-hid.c @@ -871,21 +871,6 @@ static int usb_keyboard_initfn(USBDevice *dev) return usb_hid_initfn(dev, USB_KEYBOARD); } -USBDevice *usb_tablet_init(void) -{ - return usb_create_simple(NULL /* FIXME */, "QEMU USB Tablet"); -} - -USBDevice *usb_mouse_init(void) -{ - return usb_create_simple(NULL /* FIXME */, "QEMU USB Mouse"); -} - -USBDevice *usb_keyboard_init(void) -{ - return usb_create_simple(NULL /* FIXME */, "QEMU USB Keyboard"); -} - void usb_hid_datain_cb(USBDevice *dev, void *opaque, void (*datain)(void *)) { USBHIDState *s = (USBHIDState *)dev; diff --git a/hw/usb-hub.c b/hw/usb-hub.c index 116b1d2107..0a39986468 100644 --- a/hw/usb-hub.c +++ b/hw/usb-hub.c @@ -531,18 +531,14 @@ static int usb_hub_initfn(USBDevice *dev) s->nb_ports = MAX_PORTS; /* FIXME: make configurable */ for (i = 0; i < s->nb_ports; i++) { port = &s->ports[i]; - qemu_register_usb_port(&port->port, s, i, usb_hub_attach); + usb_register_port(usb_bus_from_device(dev), + &port->port, s, i, usb_hub_attach); port->wPortStatus = PORT_STAT_POWER; port->wPortChange = 0; } return 0; } -USBDevice *usb_hub_init(int nb_ports) -{ - return usb_create_simple(NULL /* FIXME */, "QEMU USB Hub"); -} - static struct USBDeviceInfo hub_info = { .qdev.name = "QEMU USB Hub", .qdev.size = sizeof(USBHubState), diff --git a/hw/usb-musb.c b/hw/usb-musb.c index b23ed3f313..8fba84dadf 100644 --- a/hw/usb-musb.c +++ b/hw/usb-musb.c @@ -281,6 +281,7 @@ typedef struct { struct MUSBState { qemu_irq *irqs; + USBBus *bus; USBPort port; int idx; @@ -330,7 +331,8 @@ struct MUSBState { s->ep[i].epnum = i; } - qemu_register_usb_port(&s->port, s, 0, musb_attach); + s->bus = usb_bus_new(NULL /* FIXME */); + usb_register_port(s->bus, &s->port, s, 0, musb_attach); return s; } diff --git a/hw/usb-ohci.c b/hw/usb-ohci.c index e725e974b2..7f620c7d21 100644 --- a/hw/usb-ohci.c +++ b/hw/usb-ohci.c @@ -65,6 +65,7 @@ enum ohci_type { }; typedef struct { + USBBus *bus; qemu_irq irq; enum ohci_type type; int mem; @@ -1688,9 +1689,10 @@ static void usb_ohci_init(OHCIState *ohci, int num_ports, int devfn, ohci->irq = irq; ohci->type = type; + ohci->bus = usb_bus_new(NULL /* FIXME */); ohci->num_ports = num_ports; for (i = 0; i < num_ports; i++) { - qemu_register_usb_port(&ohci->rhport[i].port, ohci, i, ohci_attach); + usb_register_port(ohci->bus, &ohci->rhport[i].port, ohci, i, ohci_attach); } ohci->async_td = 0; diff --git a/hw/usb-uhci.c b/hw/usb-uhci.c index a112a6960e..2ff287b30f 100644 --- a/hw/usb-uhci.c +++ b/hw/usb-uhci.c @@ -122,6 +122,7 @@ typedef struct UHCIPort { typedef struct UHCIState { PCIDevice dev; + USBBus *bus; uint16_t cmd; /* cmd register */ uint16_t status; uint16_t intr; /* interrupt enable register */ @@ -1089,8 +1090,9 @@ void usb_uhci_piix3_init(PCIBus *bus, int devfn) pci_conf[0x3d] = 4; // interrupt pin 3 pci_conf[0x60] = 0x10; // release number + s->bus = usb_bus_new(NULL /* FIXME */); for(i = 0; i < NB_PORTS; i++) { - qemu_register_usb_port(&s->ports[i].port, s, i, uhci_attach); + usb_register_port(s->bus, &s->ports[i].port, s, i, uhci_attach); } s->frame_timer = qemu_new_timer(vm_clock, uhci_frame_timer, s); @@ -1124,8 +1126,9 @@ void usb_uhci_piix4_init(PCIBus *bus, int devfn) pci_conf[0x3d] = 4; // interrupt pin 3 pci_conf[0x60] = 0x10; // release number + s->bus = usb_bus_new(NULL /* FIXME */); for(i = 0; i < NB_PORTS; i++) { - qemu_register_usb_port(&s->ports[i].port, s, i, uhci_attach); + usb_register_port(s->bus, &s->ports[i].port, s, i, uhci_attach); } s->frame_timer = qemu_new_timer(vm_clock, uhci_frame_timer, s); diff --git a/hw/usb-wacom.c b/hw/usb-wacom.c index a5abb98f5c..4007e0fe5a 100644 --- a/hw/usb-wacom.c +++ b/hw/usb-wacom.c @@ -399,11 +399,6 @@ static int usb_wacom_initfn(USBDevice *dev) return 0; } -USBDevice *usb_wacom_init(void) -{ - return usb_create_simple(NULL /* FIXME */, "QEMU PenPartner Tablet"); -} - static struct USBDeviceInfo wacom_info = { .qdev.name = "QEMU PenPartner Tablet", .qdev.size = sizeof(USBWacomState), @@ -24,6 +24,7 @@ #include "block.h" #include "qdev.h" +#include "sys-queue.h" #define USB_TOKEN_SETUP 0x2d #define USB_TOKEN_IN 0x69 /* device -> host */ @@ -132,6 +133,7 @@ struct USBDevice { int speed; uint8_t addr; char devname[32]; + int attached; int state; uint8_t setup_buf[8]; @@ -191,7 +193,7 @@ struct USBPort { usb_attachfn attach; void *opaque; int index; /* internal port index, may be used with the opaque */ - struct USBPort *next; /* Used internally by qemu. */ + TAILQ_ENTRY(USBPort) next; }; typedef void USBCallback(USBPacket * packet, void *opaque); @@ -236,25 +238,17 @@ static inline void usb_cancel_packet(USBPacket * p) p->cancel_cb(p, p->cancel_opaque); } -int usb_device_add_dev(USBDevice *dev); -int usb_device_del_addr(int bus_num, int addr); void usb_attach(USBPort *port, USBDevice *dev); int usb_generic_handle_packet(USBDevice *s, USBPacket *p); int set_usb_string(uint8_t *buf, const char *str); void usb_send_msg(USBDevice *dev, int msg); -/* usb hub */ -USBDevice *usb_hub_init(int nb_ports); - /* usb-linux.c */ USBDevice *usb_host_device_open(const char *devname); int usb_host_device_close(const char *devname); void usb_host_info(Monitor *mon); /* usb-hid.c */ -USBDevice *usb_mouse_init(void); -USBDevice *usb_tablet_init(void); -USBDevice *usb_keyboard_init(void); void usb_hid_datain_cb(USBDevice *dev, void *opaque, void (*datain)(void *)); /* usb-msd.c */ @@ -267,17 +261,11 @@ USBDevice *usb_net_init(NICInfo *nd); /* usb-bt.c */ USBDevice *usb_bt_init(HCIInfo *hci); -/* usb-wacom.c */ -USBDevice *usb_wacom_init(void); - /* usb-serial.c */ USBDevice *usb_serial_init(const char *filename); /* usb ports of the VM */ -void qemu_register_usb_port(USBPort *port, void *opaque, int index, - usb_attachfn attach); - #define VM_USB_HUB_SIZE 8 /* usb-musb.c */ @@ -319,4 +307,14 @@ USBBus *usb_bus_new(DeviceState *host); USBBus *usb_bus_find(int busnr); void usb_qdev_register(USBDeviceInfo *info); void usb_qdev_register_many(USBDeviceInfo *info); +USBDevice *usb_create(USBBus *bus, const char *name); USBDevice *usb_create_simple(USBBus *bus, const char *name); +void usb_register_port(USBBus *bus, USBPort *port, void *opaque, int index, + usb_attachfn attach); +int usb_device_attach(USBDevice *dev); +int usb_device_delete_addr(int busnr, int addr); + +static inline USBBus *usb_bus_from_device(USBDevice *d) +{ + return DO_UPCAST(USBBus, qbus, d->qdev.parent_bus); +} |