Statistics
| Branch: | Revision:

root / hw / usb-bus.c @ a5d2f727

History | View | Annotate | Download (4.8 kB)

1
#include "hw.h"
2
#include "usb.h"
3
#include "qdev.h"
4
#include "sysemu.h"
5
#include "monitor.h"
6

    
7
static void usb_bus_dev_print(Monitor *mon, DeviceState *qdev, int indent);
8

    
9
static struct BusInfo usb_bus_info = {
10
    .name      = "USB",
11
    .size      = sizeof(USBBus),
12
    .print_dev = usb_bus_dev_print,
13
};
14
static int next_usb_bus = 0;
15
static TAILQ_HEAD(, USBBus) busses = TAILQ_HEAD_INITIALIZER(busses);
16

    
17
USBBus *usb_bus_new(DeviceState *host)
18
{
19
    USBBus *bus;
20

    
21
    bus = FROM_QBUS(USBBus, qbus_create(&usb_bus_info, host, NULL));
22
    bus->busnr = next_usb_bus++;
23
    TAILQ_INIT(&bus->free);
24
    TAILQ_INIT(&bus->used);
25
    TAILQ_INSERT_TAIL(&busses, bus, next);
26
    return bus;
27
}
28

    
29
USBBus *usb_bus_find(int busnr)
30
{
31
    USBBus *bus;
32

    
33
    if (-1 == busnr)
34
        return TAILQ_FIRST(&busses);
35
    TAILQ_FOREACH(bus, &busses, next) {
36
        if (bus->busnr == busnr)
37
            return bus;
38
    }
39
    return NULL;
40
}
41

    
42
static int usb_qdev_init(DeviceState *qdev, DeviceInfo *base)
43
{
44
    USBDevice *dev = DO_UPCAST(USBDevice, qdev, qdev);
45
    USBDeviceInfo *info = DO_UPCAST(USBDeviceInfo, qdev, base);
46
    int rc;
47

    
48
    pstrcpy(dev->devname, sizeof(dev->devname), qdev->info->name);
49
    dev->info = info;
50
    rc = dev->info->init(dev);
51
    if (rc == 0)
52
        usb_device_attach(dev);
53
    return rc;
54
}
55

    
56
void usb_qdev_register(USBDeviceInfo *info)
57
{
58
    info->qdev.bus_info = &usb_bus_info;
59
    info->qdev.init     = usb_qdev_init;
60
    qdev_register(&info->qdev);
61
}
62

    
63
void usb_qdev_register_many(USBDeviceInfo *info)
64
{
65
    while (info->qdev.name) {
66
        usb_qdev_register(info);
67
        info++;
68
    }
69
}
70

    
71
USBDevice *usb_create(USBBus *bus, const char *name)
72
{
73
    DeviceState *dev;
74

    
75
#if 1
76
    /* temporary stopgap until all usb is properly qdev-ified */
77
    if (!bus) {
78
        bus = usb_bus_find(-1);
79
        if (!bus)
80
            return NULL;
81
        fprintf(stderr, "%s: no bus specified, using \"%s\" for \"%s\"\n",
82
                __FUNCTION__, bus->qbus.name, name);
83
    }
84
#endif
85

    
86
    dev = qdev_create(&bus->qbus, name);
87
    return DO_UPCAST(USBDevice, qdev, dev);
88
}
89

    
90
USBDevice *usb_create_simple(USBBus *bus, const char *name)
91
{
92
    USBDevice *dev = usb_create(bus, name);
93
    qdev_init(&dev->qdev);
94
    return dev;
95
}
96

    
97
void usb_register_port(USBBus *bus, USBPort *port, void *opaque, int index,
98
                       usb_attachfn attach)
99
{
100
    port->opaque = opaque;
101
    port->index = index;
102
    port->attach = attach;
103
    TAILQ_INSERT_TAIL(&bus->free, port, next);
104
    bus->nfree++;
105
}
106

    
107
static void do_attach(USBDevice *dev)
108
{
109
    USBBus *bus = usb_bus_from_device(dev);
110
    USBPort *port;
111

    
112
    if (dev->attached) {
113
        fprintf(stderr, "Warning: tried to attach usb device %s twice\n",
114
                dev->devname);
115
        return;
116
    }
117
    dev->attached++;
118

    
119
    port = TAILQ_FIRST(&bus->free);
120
    TAILQ_REMOVE(&bus->free, port, next);
121
    bus->nfree--;
122

    
123
    usb_attach(port, dev);
124

    
125
    TAILQ_INSERT_TAIL(&bus->used, port, next);
126
    bus->nused++;
127
}
128

    
129
int usb_device_attach(USBDevice *dev)
130
{
131
    USBBus *bus = usb_bus_from_device(dev);
132
    USBDevice *hub;
133

    
134
    if (bus->nfree == 1) {
135
        /* Create a new hub and chain it on.  */
136
        hub = usb_create_simple(bus, "QEMU USB Hub");
137
    }
138
    do_attach(dev);
139
    return 0;
140
}
141

    
142
int usb_device_delete_addr(int busnr, int addr)
143
{
144
    USBBus *bus;
145
    USBPort *port;
146
    USBDevice *dev;
147

    
148
    bus = usb_bus_find(busnr);
149
    if (!bus)
150
        return -1;
151

    
152
    TAILQ_FOREACH(port, &bus->used, next) {
153
        if (port->dev->addr == addr)
154
            break;
155
    }
156
    if (!port)
157
        return -1;
158

    
159
    dev = port->dev;
160
    TAILQ_REMOVE(&bus->used, port, next);
161
    bus->nused--;
162

    
163
    usb_attach(port, NULL);
164
    dev->info->handle_destroy(dev);
165

    
166
    TAILQ_INSERT_TAIL(&bus->free, port, next);
167
    bus->nfree++;
168
    return 0;
169
}
170

    
171
static const char *usb_speed(unsigned int speed)
172
{
173
    static const char *txt[] = {
174
        [ USB_SPEED_LOW  ] = "1.5",
175
        [ USB_SPEED_FULL ] = "12",
176
        [ USB_SPEED_HIGH ] = "480",
177
    };
178
    if (speed >= ARRAY_SIZE(txt))
179
        return "?";
180
    return txt[speed];
181
}
182

    
183
static void usb_bus_dev_print(Monitor *mon, DeviceState *qdev, int indent)
184
{
185
    USBDevice *dev = DO_UPCAST(USBDevice, qdev, qdev);
186
    USBBus *bus = usb_bus_from_device(dev);
187

    
188
    monitor_printf(mon, "%*saddr %d.%d, speed %s, name %s\n", indent, "",
189
                   bus->busnr, dev->addr,
190
                   usb_speed(dev->speed), dev->devname);
191
}
192

    
193
void usb_info(Monitor *mon)
194
{
195
    USBBus *bus;
196
    USBDevice *dev;
197
    USBPort *port;
198

    
199
    if (TAILQ_EMPTY(&busses)) {
200
        monitor_printf(mon, "USB support not enabled\n");
201
        return;
202
    }
203

    
204
    TAILQ_FOREACH(bus, &busses, next) {
205
        TAILQ_FOREACH(port, &bus->used, next) {
206
            dev = port->dev;
207
            if (!dev)
208
                continue;
209
            monitor_printf(mon, "  Device %d.%d, Speed %s Mb/s, Product %s\n",
210
                           bus->busnr, dev->addr, usb_speed(dev->speed), dev->devname);
211
        }
212
    }
213
}
214