Statistics
| Branch: | Revision:

root / hw / usb-bus.c @ 93148aa5

History | View | Annotate | Download (14.7 kB)

1 806b6024 Gerd Hoffmann
#include "hw.h"
2 806b6024 Gerd Hoffmann
#include "usb.h"
3 806b6024 Gerd Hoffmann
#include "qdev.h"
4 a5d2f727 Gerd Hoffmann
#include "sysemu.h"
5 a5d2f727 Gerd Hoffmann
#include "monitor.h"
6 891fb2cd Gerd Hoffmann
#include "trace.h"
7 a5d2f727 Gerd Hoffmann
8 a5d2f727 Gerd Hoffmann
static void usb_bus_dev_print(Monitor *mon, DeviceState *qdev, int indent);
9 c7a2196a Gerd Hoffmann
10 c7a2196a Gerd Hoffmann
static char *usb_get_dev_path(DeviceState *dev);
11 70d31cb2 Gerd Hoffmann
static char *usb_get_fw_dev_path(DeviceState *qdev);
12 f462141f Gerd Hoffmann
static int usb_qdev_exit(DeviceState *qdev);
13 806b6024 Gerd Hoffmann
14 806b6024 Gerd Hoffmann
static struct BusInfo usb_bus_info = {
15 a5d2f727 Gerd Hoffmann
    .name      = "USB",
16 a5d2f727 Gerd Hoffmann
    .size      = sizeof(USBBus),
17 a5d2f727 Gerd Hoffmann
    .print_dev = usb_bus_dev_print,
18 c7a2196a Gerd Hoffmann
    .get_dev_path = usb_get_dev_path,
19 70d31cb2 Gerd Hoffmann
    .get_fw_dev_path = usb_get_fw_dev_path,
20 5f69076b Gerd Hoffmann
    .props      = (Property[]) {
21 5f69076b Gerd Hoffmann
        DEFINE_PROP_STRING("port", USBDevice, port_path),
22 5f69076b Gerd Hoffmann
        DEFINE_PROP_END_OF_LIST()
23 5f69076b Gerd Hoffmann
    },
24 806b6024 Gerd Hoffmann
};
25 806b6024 Gerd Hoffmann
static int next_usb_bus = 0;
26 72cf2d4f Blue Swirl
static QTAILQ_HEAD(, USBBus) busses = QTAILQ_HEAD_INITIALIZER(busses);
27 806b6024 Gerd Hoffmann
28 c1ecb40a Gerd Hoffmann
const VMStateDescription vmstate_usb_device = {
29 c1ecb40a Gerd Hoffmann
    .name = "USBDevice",
30 c1ecb40a Gerd Hoffmann
    .version_id = 1,
31 c1ecb40a Gerd Hoffmann
    .minimum_version_id = 1,
32 c1ecb40a Gerd Hoffmann
    .fields = (VMStateField []) {
33 c1ecb40a Gerd Hoffmann
        VMSTATE_UINT8(addr, USBDevice),
34 c1ecb40a Gerd Hoffmann
        VMSTATE_INT32(state, USBDevice),
35 c1ecb40a Gerd Hoffmann
        VMSTATE_INT32(remote_wakeup, USBDevice),
36 c1ecb40a Gerd Hoffmann
        VMSTATE_INT32(setup_state, USBDevice),
37 c1ecb40a Gerd Hoffmann
        VMSTATE_INT32(setup_len, USBDevice),
38 c1ecb40a Gerd Hoffmann
        VMSTATE_INT32(setup_index, USBDevice),
39 c1ecb40a Gerd Hoffmann
        VMSTATE_UINT8_ARRAY(setup_buf, USBDevice, 8),
40 c1ecb40a Gerd Hoffmann
        VMSTATE_END_OF_LIST(),
41 c1ecb40a Gerd Hoffmann
    }
42 c1ecb40a Gerd Hoffmann
};
43 c1ecb40a Gerd Hoffmann
44 07771f6f Gerd Hoffmann
void usb_bus_new(USBBus *bus, USBBusOps *ops, DeviceState *host)
45 806b6024 Gerd Hoffmann
{
46 b2317837 Gerd Hoffmann
    qbus_create_inplace(&bus->qbus, &usb_bus_info, host, NULL);
47 07771f6f Gerd Hoffmann
    bus->ops = ops;
48 806b6024 Gerd Hoffmann
    bus->busnr = next_usb_bus++;
49 ef816d83 Gerd Hoffmann
    bus->qbus.allow_hotplug = 1; /* Yes, we can */
50 72cf2d4f Blue Swirl
    QTAILQ_INIT(&bus->free);
51 72cf2d4f Blue Swirl
    QTAILQ_INIT(&bus->used);
52 72cf2d4f Blue Swirl
    QTAILQ_INSERT_TAIL(&busses, bus, next);
53 806b6024 Gerd Hoffmann
}
54 806b6024 Gerd Hoffmann
55 806b6024 Gerd Hoffmann
USBBus *usb_bus_find(int busnr)
56 806b6024 Gerd Hoffmann
{
57 806b6024 Gerd Hoffmann
    USBBus *bus;
58 806b6024 Gerd Hoffmann
59 806b6024 Gerd Hoffmann
    if (-1 == busnr)
60 72cf2d4f Blue Swirl
        return QTAILQ_FIRST(&busses);
61 72cf2d4f Blue Swirl
    QTAILQ_FOREACH(bus, &busses, next) {
62 806b6024 Gerd Hoffmann
        if (bus->busnr == busnr)
63 806b6024 Gerd Hoffmann
            return bus;
64 806b6024 Gerd Hoffmann
    }
65 806b6024 Gerd Hoffmann
    return NULL;
66 806b6024 Gerd Hoffmann
}
67 806b6024 Gerd Hoffmann
68 62aed765 Anthony Liguori
static int usb_device_init(USBDevice *dev)
69 62aed765 Anthony Liguori
{
70 62aed765 Anthony Liguori
    USBDeviceClass *klass = USB_DEVICE_GET_CLASS(dev);
71 62aed765 Anthony Liguori
    if (klass->init) {
72 62aed765 Anthony Liguori
        return klass->init(dev);
73 62aed765 Anthony Liguori
    }
74 62aed765 Anthony Liguori
    return 0;
75 62aed765 Anthony Liguori
}
76 62aed765 Anthony Liguori
77 73796fe6 Gerd Hoffmann
USBDevice *usb_device_find_device(USBDevice *dev, uint8_t addr)
78 62aed765 Anthony Liguori
{
79 62aed765 Anthony Liguori
    USBDeviceClass *klass = USB_DEVICE_GET_CLASS(dev);
80 73796fe6 Gerd Hoffmann
    if (klass->find_device) {
81 73796fe6 Gerd Hoffmann
        return klass->find_device(dev, addr);
82 62aed765 Anthony Liguori
    }
83 73796fe6 Gerd Hoffmann
    return NULL;
84 62aed765 Anthony Liguori
}
85 62aed765 Anthony Liguori
86 62aed765 Anthony Liguori
static void usb_device_handle_destroy(USBDevice *dev)
87 62aed765 Anthony Liguori
{
88 62aed765 Anthony Liguori
    USBDeviceClass *klass = USB_DEVICE_GET_CLASS(dev);
89 62aed765 Anthony Liguori
    if (klass->handle_destroy) {
90 62aed765 Anthony Liguori
        klass->handle_destroy(dev);
91 62aed765 Anthony Liguori
    }
92 62aed765 Anthony Liguori
}
93 62aed765 Anthony Liguori
94 62aed765 Anthony Liguori
void usb_device_cancel_packet(USBDevice *dev, USBPacket *p)
95 62aed765 Anthony Liguori
{
96 62aed765 Anthony Liguori
    USBDeviceClass *klass = USB_DEVICE_GET_CLASS(dev);
97 62aed765 Anthony Liguori
    if (klass->cancel_packet) {
98 62aed765 Anthony Liguori
        klass->cancel_packet(dev, p);
99 62aed765 Anthony Liguori
    }
100 62aed765 Anthony Liguori
}
101 62aed765 Anthony Liguori
102 62aed765 Anthony Liguori
void usb_device_handle_attach(USBDevice *dev)
103 62aed765 Anthony Liguori
{
104 62aed765 Anthony Liguori
    USBDeviceClass *klass = USB_DEVICE_GET_CLASS(dev);
105 62aed765 Anthony Liguori
    if (klass->handle_attach) {
106 62aed765 Anthony Liguori
        klass->handle_attach(dev);
107 62aed765 Anthony Liguori
    }
108 62aed765 Anthony Liguori
}
109 62aed765 Anthony Liguori
110 62aed765 Anthony Liguori
void usb_device_handle_reset(USBDevice *dev)
111 62aed765 Anthony Liguori
{
112 62aed765 Anthony Liguori
    USBDeviceClass *klass = USB_DEVICE_GET_CLASS(dev);
113 62aed765 Anthony Liguori
    if (klass->handle_reset) {
114 62aed765 Anthony Liguori
        klass->handle_reset(dev);
115 62aed765 Anthony Liguori
    }
116 62aed765 Anthony Liguori
}
117 62aed765 Anthony Liguori
118 62aed765 Anthony Liguori
int usb_device_handle_control(USBDevice *dev, USBPacket *p, int request,
119 62aed765 Anthony Liguori
                              int value, int index, int length, uint8_t *data)
120 62aed765 Anthony Liguori
{
121 62aed765 Anthony Liguori
    USBDeviceClass *klass = USB_DEVICE_GET_CLASS(dev);
122 62aed765 Anthony Liguori
    if (klass->handle_control) {
123 62aed765 Anthony Liguori
        return klass->handle_control(dev, p, request, value, index, length,
124 62aed765 Anthony Liguori
                                         data);
125 62aed765 Anthony Liguori
    }
126 62aed765 Anthony Liguori
    return -ENOSYS;
127 62aed765 Anthony Liguori
}
128 62aed765 Anthony Liguori
129 62aed765 Anthony Liguori
int usb_device_handle_data(USBDevice *dev, USBPacket *p)
130 62aed765 Anthony Liguori
{
131 62aed765 Anthony Liguori
    USBDeviceClass *klass = USB_DEVICE_GET_CLASS(dev);
132 62aed765 Anthony Liguori
    if (klass->handle_data) {
133 62aed765 Anthony Liguori
        return klass->handle_data(dev, p);
134 62aed765 Anthony Liguori
    }
135 62aed765 Anthony Liguori
    return -ENOSYS;
136 62aed765 Anthony Liguori
}
137 62aed765 Anthony Liguori
138 62aed765 Anthony Liguori
const char *usb_device_get_product_desc(USBDevice *dev)
139 62aed765 Anthony Liguori
{
140 62aed765 Anthony Liguori
    USBDeviceClass *klass = USB_DEVICE_GET_CLASS(dev);
141 62aed765 Anthony Liguori
    return klass->product_desc;
142 62aed765 Anthony Liguori
}
143 62aed765 Anthony Liguori
144 62aed765 Anthony Liguori
const USBDesc *usb_device_get_usb_desc(USBDevice *dev)
145 62aed765 Anthony Liguori
{
146 62aed765 Anthony Liguori
    USBDeviceClass *klass = USB_DEVICE_GET_CLASS(dev);
147 62aed765 Anthony Liguori
    return klass->usb_desc;
148 62aed765 Anthony Liguori
}
149 62aed765 Anthony Liguori
150 62aed765 Anthony Liguori
void usb_device_set_interface(USBDevice *dev, int interface,
151 62aed765 Anthony Liguori
                              int alt_old, int alt_new)
152 62aed765 Anthony Liguori
{
153 62aed765 Anthony Liguori
    USBDeviceClass *klass = USB_DEVICE_GET_CLASS(dev);
154 62aed765 Anthony Liguori
    if (klass->set_interface) {
155 62aed765 Anthony Liguori
        klass->set_interface(dev, interface, alt_old, alt_new);
156 62aed765 Anthony Liguori
    }
157 62aed765 Anthony Liguori
}
158 62aed765 Anthony Liguori
159 d307af79 Anthony Liguori
static int usb_qdev_init(DeviceState *qdev)
160 806b6024 Gerd Hoffmann
{
161 62aed765 Anthony Liguori
    USBDevice *dev = USB_DEVICE(qdev);
162 806b6024 Gerd Hoffmann
    int rc;
163 806b6024 Gerd Hoffmann
164 62aed765 Anthony Liguori
    pstrcpy(dev->product_desc, sizeof(dev->product_desc),
165 62aed765 Anthony Liguori
            usb_device_get_product_desc(dev));
166 61e094c0 Gerd Hoffmann
    dev->auto_attach = 1;
167 132a3f55 Gerd Hoffmann
    QLIST_INIT(&dev->strings);
168 d8e17efd Gerd Hoffmann
    usb_ep_init(dev);
169 891fb2cd Gerd Hoffmann
    rc = usb_claim_port(dev);
170 f462141f Gerd Hoffmann
    if (rc != 0) {
171 db3a5ed7 Stefan Hajnoczi
        return rc;
172 891fb2cd Gerd Hoffmann
    }
173 62aed765 Anthony Liguori
    rc = usb_device_init(dev);
174 f462141f Gerd Hoffmann
    if (rc != 0) {
175 db3a5ed7 Stefan Hajnoczi
        usb_release_port(dev);
176 db3a5ed7 Stefan Hajnoczi
        return rc;
177 f462141f Gerd Hoffmann
    }
178 f462141f Gerd Hoffmann
    if (dev->auto_attach) {
179 fa19bf83 Hans de Goede
        rc = usb_device_attach(dev);
180 f462141f Gerd Hoffmann
        if (rc != 0) {
181 db3a5ed7 Stefan Hajnoczi
            usb_qdev_exit(qdev);
182 db3a5ed7 Stefan Hajnoczi
            return rc;
183 f462141f Gerd Hoffmann
        }
184 891fb2cd Gerd Hoffmann
    }
185 f462141f Gerd Hoffmann
    return 0;
186 806b6024 Gerd Hoffmann
}
187 806b6024 Gerd Hoffmann
188 a8e662b5 Gerd Hoffmann
static int usb_qdev_exit(DeviceState *qdev)
189 a8e662b5 Gerd Hoffmann
{
190 62aed765 Anthony Liguori
    USBDevice *dev = USB_DEVICE(qdev);
191 a8e662b5 Gerd Hoffmann
192 290a5c60 Hans de Goede
    if (dev->attached) {
193 290a5c60 Hans de Goede
        usb_device_detach(dev);
194 290a5c60 Hans de Goede
    }
195 62aed765 Anthony Liguori
    usb_device_handle_destroy(dev);
196 891fb2cd Gerd Hoffmann
    if (dev->port) {
197 891fb2cd Gerd Hoffmann
        usb_release_port(dev);
198 891fb2cd Gerd Hoffmann
    }
199 a8e662b5 Gerd Hoffmann
    return 0;
200 a8e662b5 Gerd Hoffmann
}
201 a8e662b5 Gerd Hoffmann
202 62aed765 Anthony Liguori
typedef struct LegacyUSBFactory
203 806b6024 Gerd Hoffmann
{
204 62aed765 Anthony Liguori
    const char *name;
205 62aed765 Anthony Liguori
    const char *usbdevice_name;
206 3741715c Jan Kiszka
    USBDevice *(*usbdevice_init)(USBBus *bus, const char *params);
207 62aed765 Anthony Liguori
} LegacyUSBFactory;
208 806b6024 Gerd Hoffmann
209 62aed765 Anthony Liguori
static GSList *legacy_usb_factory;
210 62aed765 Anthony Liguori
211 ba02430f Anthony Liguori
void usb_legacy_register(const char *typename, const char *usbdevice_name,
212 3741715c Jan Kiszka
                         USBDevice *(*usbdevice_init)(USBBus *bus,
213 3741715c Jan Kiszka
                                                      const char *params))
214 806b6024 Gerd Hoffmann
{
215 62aed765 Anthony Liguori
    if (usbdevice_name) {
216 62aed765 Anthony Liguori
        LegacyUSBFactory *f = g_malloc0(sizeof(*f));
217 ba02430f Anthony Liguori
        f->name = typename;
218 62aed765 Anthony Liguori
        f->usbdevice_name = usbdevice_name;
219 62aed765 Anthony Liguori
        f->usbdevice_init = usbdevice_init;
220 62aed765 Anthony Liguori
        legacy_usb_factory = g_slist_append(legacy_usb_factory, f);
221 806b6024 Gerd Hoffmann
    }
222 806b6024 Gerd Hoffmann
}
223 806b6024 Gerd Hoffmann
224 a5d2f727 Gerd Hoffmann
USBDevice *usb_create(USBBus *bus, const char *name)
225 806b6024 Gerd Hoffmann
{
226 806b6024 Gerd Hoffmann
    DeviceState *dev;
227 806b6024 Gerd Hoffmann
228 806b6024 Gerd Hoffmann
    dev = qdev_create(&bus->qbus, name);
229 62aed765 Anthony Liguori
    return USB_DEVICE(dev);
230 806b6024 Gerd Hoffmann
}
231 a5d2f727 Gerd Hoffmann
232 a5d2f727 Gerd Hoffmann
USBDevice *usb_create_simple(USBBus *bus, const char *name)
233 a5d2f727 Gerd Hoffmann
{
234 a5d2f727 Gerd Hoffmann
    USBDevice *dev = usb_create(bus, name);
235 2af2a1b8 Gerd Hoffmann
    int rc;
236 2af2a1b8 Gerd Hoffmann
237 d44168ff Paul Brook
    if (!dev) {
238 be62a2eb Markus Armbruster
        error_report("Failed to create USB device '%s'", name);
239 2af2a1b8 Gerd Hoffmann
        return NULL;
240 2af2a1b8 Gerd Hoffmann
    }
241 2af2a1b8 Gerd Hoffmann
    rc = qdev_init(&dev->qdev);
242 2af2a1b8 Gerd Hoffmann
    if (rc < 0) {
243 be62a2eb Markus Armbruster
        error_report("Failed to initialize USB device '%s'", name);
244 2af2a1b8 Gerd Hoffmann
        return NULL;
245 d44168ff Paul Brook
    }
246 a5d2f727 Gerd Hoffmann
    return dev;
247 a5d2f727 Gerd Hoffmann
}
248 a5d2f727 Gerd Hoffmann
249 090ac642 Hans de Goede
static void usb_fill_port(USBPort *port, void *opaque, int index,
250 090ac642 Hans de Goede
                          USBPortOps *ops, int speedmask)
251 a5d2f727 Gerd Hoffmann
{
252 a5d2f727 Gerd Hoffmann
    port->opaque = opaque;
253 a5d2f727 Gerd Hoffmann
    port->index = index;
254 0d86d2be Gerd Hoffmann
    port->ops = ops;
255 843d4e0c Gerd Hoffmann
    port->speedmask = speedmask;
256 3631e6c8 Hans de Goede
    usb_port_location(port, NULL, index + 1);
257 090ac642 Hans de Goede
}
258 090ac642 Hans de Goede
259 090ac642 Hans de Goede
void usb_register_port(USBBus *bus, USBPort *port, void *opaque, int index,
260 090ac642 Hans de Goede
                       USBPortOps *ops, int speedmask)
261 090ac642 Hans de Goede
{
262 090ac642 Hans de Goede
    usb_fill_port(port, opaque, index, ops, speedmask);
263 72cf2d4f Blue Swirl
    QTAILQ_INSERT_TAIL(&bus->free, port, next);
264 a5d2f727 Gerd Hoffmann
    bus->nfree++;
265 a5d2f727 Gerd Hoffmann
}
266 a5d2f727 Gerd Hoffmann
267 ae60fea9 Hans de Goede
int usb_register_companion(const char *masterbus, USBPort *ports[],
268 ae60fea9 Hans de Goede
                           uint32_t portcount, uint32_t firstport,
269 ae60fea9 Hans de Goede
                           void *opaque, USBPortOps *ops, int speedmask)
270 ae60fea9 Hans de Goede
{
271 ae60fea9 Hans de Goede
    USBBus *bus;
272 ae60fea9 Hans de Goede
    int i;
273 ae60fea9 Hans de Goede
274 ae60fea9 Hans de Goede
    QTAILQ_FOREACH(bus, &busses, next) {
275 ae60fea9 Hans de Goede
        if (strcmp(bus->qbus.name, masterbus) == 0) {
276 ae60fea9 Hans de Goede
            break;
277 ae60fea9 Hans de Goede
        }
278 ae60fea9 Hans de Goede
    }
279 ae60fea9 Hans de Goede
280 ae60fea9 Hans de Goede
    if (!bus || !bus->ops->register_companion) {
281 ae60fea9 Hans de Goede
        qerror_report(QERR_INVALID_PARAMETER_VALUE, "masterbus",
282 ae60fea9 Hans de Goede
                      "an USB masterbus");
283 ae60fea9 Hans de Goede
        if (bus) {
284 ae60fea9 Hans de Goede
            error_printf_unless_qmp(
285 ae60fea9 Hans de Goede
                "USB bus '%s' does not allow companion controllers\n",
286 ae60fea9 Hans de Goede
                masterbus);
287 ae60fea9 Hans de Goede
        }
288 ae60fea9 Hans de Goede
        return -1;
289 ae60fea9 Hans de Goede
    }
290 ae60fea9 Hans de Goede
291 ae60fea9 Hans de Goede
    for (i = 0; i < portcount; i++) {
292 ae60fea9 Hans de Goede
        usb_fill_port(ports[i], opaque, i, ops, speedmask);
293 ae60fea9 Hans de Goede
    }
294 ae60fea9 Hans de Goede
295 ae60fea9 Hans de Goede
    return bus->ops->register_companion(bus, ports, portcount, firstport);
296 ae60fea9 Hans de Goede
}
297 ae60fea9 Hans de Goede
298 c7a2196a Gerd Hoffmann
void usb_port_location(USBPort *downstream, USBPort *upstream, int portnr)
299 c7a2196a Gerd Hoffmann
{
300 c7a2196a Gerd Hoffmann
    if (upstream) {
301 c7a2196a Gerd Hoffmann
        snprintf(downstream->path, sizeof(downstream->path), "%s.%d",
302 c7a2196a Gerd Hoffmann
                 upstream->path, portnr);
303 c7a2196a Gerd Hoffmann
    } else {
304 c7a2196a Gerd Hoffmann
        snprintf(downstream->path, sizeof(downstream->path), "%d", portnr);
305 c7a2196a Gerd Hoffmann
    }
306 c7a2196a Gerd Hoffmann
}
307 c7a2196a Gerd Hoffmann
308 a8e662b5 Gerd Hoffmann
void usb_unregister_port(USBBus *bus, USBPort *port)
309 a8e662b5 Gerd Hoffmann
{
310 a8e662b5 Gerd Hoffmann
    if (port->dev)
311 a8e662b5 Gerd Hoffmann
        qdev_free(&port->dev->qdev);
312 a8e662b5 Gerd Hoffmann
    QTAILQ_REMOVE(&bus->free, port, next);
313 a8e662b5 Gerd Hoffmann
    bus->nfree--;
314 a8e662b5 Gerd Hoffmann
}
315 a8e662b5 Gerd Hoffmann
316 891fb2cd Gerd Hoffmann
int usb_claim_port(USBDevice *dev)
317 a5d2f727 Gerd Hoffmann
{
318 a5d2f727 Gerd Hoffmann
    USBBus *bus = usb_bus_from_device(dev);
319 a5d2f727 Gerd Hoffmann
    USBPort *port;
320 a5d2f727 Gerd Hoffmann
321 891fb2cd Gerd Hoffmann
    assert(dev->port == NULL);
322 891fb2cd Gerd Hoffmann
323 5f69076b Gerd Hoffmann
    if (dev->port_path) {
324 5f69076b Gerd Hoffmann
        QTAILQ_FOREACH(port, &bus->free, next) {
325 5f69076b Gerd Hoffmann
            if (strcmp(port->path, dev->port_path) == 0) {
326 5f69076b Gerd Hoffmann
                break;
327 5f69076b Gerd Hoffmann
            }
328 5f69076b Gerd Hoffmann
        }
329 5f69076b Gerd Hoffmann
        if (port == NULL) {
330 be62a2eb Markus Armbruster
            error_report("Error: usb port %s (bus %s) not found (in use?)",
331 891fb2cd Gerd Hoffmann
                         dev->port_path, bus->qbus.name);
332 fa19bf83 Hans de Goede
            return -1;
333 5f69076b Gerd Hoffmann
        }
334 5f69076b Gerd Hoffmann
    } else {
335 f79f2bfc Anthony Liguori
        if (bus->nfree == 1 && strcmp(object_get_typename(OBJECT(dev)), "usb-hub") != 0) {
336 891fb2cd Gerd Hoffmann
            /* Create a new hub and chain it on */
337 891fb2cd Gerd Hoffmann
            usb_create_simple(bus, "usb-hub");
338 891fb2cd Gerd Hoffmann
        }
339 891fb2cd Gerd Hoffmann
        if (bus->nfree == 0) {
340 891fb2cd Gerd Hoffmann
            error_report("Error: tried to attach usb device %s to a bus "
341 be62a2eb Markus Armbruster
                         "with no free ports", dev->product_desc);
342 891fb2cd Gerd Hoffmann
            return -1;
343 891fb2cd Gerd Hoffmann
        }
344 5f69076b Gerd Hoffmann
        port = QTAILQ_FIRST(&bus->free);
345 5f69076b Gerd Hoffmann
    }
346 891fb2cd Gerd Hoffmann
    trace_usb_port_claim(bus->busnr, port->path);
347 a5d2f727 Gerd Hoffmann
348 72cf2d4f Blue Swirl
    QTAILQ_REMOVE(&bus->free, port, next);
349 a5d2f727 Gerd Hoffmann
    bus->nfree--;
350 a5d2f727 Gerd Hoffmann
351 891fb2cd Gerd Hoffmann
    dev->port = port;
352 891fb2cd Gerd Hoffmann
    port->dev = dev;
353 a5d2f727 Gerd Hoffmann
354 72cf2d4f Blue Swirl
    QTAILQ_INSERT_TAIL(&bus->used, port, next);
355 a5d2f727 Gerd Hoffmann
    bus->nused++;
356 fa19bf83 Hans de Goede
    return 0;
357 a5d2f727 Gerd Hoffmann
}
358 a5d2f727 Gerd Hoffmann
359 891fb2cd Gerd Hoffmann
void usb_release_port(USBDevice *dev)
360 a5d2f727 Gerd Hoffmann
{
361 a5d2f727 Gerd Hoffmann
    USBBus *bus = usb_bus_from_device(dev);
362 891fb2cd Gerd Hoffmann
    USBPort *port = dev->port;
363 a5d2f727 Gerd Hoffmann
364 891fb2cd Gerd Hoffmann
    assert(port != NULL);
365 891fb2cd Gerd Hoffmann
    trace_usb_port_release(bus->busnr, port->path);
366 891fb2cd Gerd Hoffmann
367 891fb2cd Gerd Hoffmann
    QTAILQ_REMOVE(&bus->used, port, next);
368 891fb2cd Gerd Hoffmann
    bus->nused--;
369 891fb2cd Gerd Hoffmann
370 891fb2cd Gerd Hoffmann
    dev->port = NULL;
371 891fb2cd Gerd Hoffmann
    port->dev = NULL;
372 891fb2cd Gerd Hoffmann
373 891fb2cd Gerd Hoffmann
    QTAILQ_INSERT_TAIL(&bus->free, port, next);
374 891fb2cd Gerd Hoffmann
    bus->nfree++;
375 a5d2f727 Gerd Hoffmann
}
376 a5d2f727 Gerd Hoffmann
377 891fb2cd Gerd Hoffmann
int usb_device_attach(USBDevice *dev)
378 a8e662b5 Gerd Hoffmann
{
379 a8e662b5 Gerd Hoffmann
    USBBus *bus = usb_bus_from_device(dev);
380 891fb2cd Gerd Hoffmann
    USBPort *port = dev->port;
381 a8e662b5 Gerd Hoffmann
382 891fb2cd Gerd Hoffmann
    assert(port != NULL);
383 891fb2cd Gerd Hoffmann
    assert(!dev->attached);
384 891fb2cd Gerd Hoffmann
    trace_usb_port_attach(bus->busnr, port->path);
385 891fb2cd Gerd Hoffmann
386 891fb2cd Gerd Hoffmann
    if (!(port->speedmask & dev->speedmask)) {
387 891fb2cd Gerd Hoffmann
        error_report("Warning: speed mismatch trying to attach "
388 be62a2eb Markus Armbruster
                     "usb device %s to bus %s",
389 891fb2cd Gerd Hoffmann
                     dev->product_desc, bus->qbus.name);
390 a8e662b5 Gerd Hoffmann
        return -1;
391 a8e662b5 Gerd Hoffmann
    }
392 a8e662b5 Gerd Hoffmann
393 891fb2cd Gerd Hoffmann
    dev->attached++;
394 891fb2cd Gerd Hoffmann
    usb_attach(port);
395 a8e662b5 Gerd Hoffmann
396 891fb2cd Gerd Hoffmann
    return 0;
397 891fb2cd Gerd Hoffmann
}
398 891fb2cd Gerd Hoffmann
399 891fb2cd Gerd Hoffmann
int usb_device_detach(USBDevice *dev)
400 891fb2cd Gerd Hoffmann
{
401 891fb2cd Gerd Hoffmann
    USBBus *bus = usb_bus_from_device(dev);
402 891fb2cd Gerd Hoffmann
    USBPort *port = dev->port;
403 a8e662b5 Gerd Hoffmann
404 891fb2cd Gerd Hoffmann
    assert(port != NULL);
405 891fb2cd Gerd Hoffmann
    assert(dev->attached);
406 891fb2cd Gerd Hoffmann
    trace_usb_port_detach(bus->busnr, port->path);
407 a8e662b5 Gerd Hoffmann
408 891fb2cd Gerd Hoffmann
    usb_detach(port);
409 891fb2cd Gerd Hoffmann
    dev->attached--;
410 a8e662b5 Gerd Hoffmann
    return 0;
411 a8e662b5 Gerd Hoffmann
}
412 a8e662b5 Gerd Hoffmann
413 a5d2f727 Gerd Hoffmann
int usb_device_delete_addr(int busnr, int addr)
414 a5d2f727 Gerd Hoffmann
{
415 a5d2f727 Gerd Hoffmann
    USBBus *bus;
416 a5d2f727 Gerd Hoffmann
    USBPort *port;
417 a5d2f727 Gerd Hoffmann
    USBDevice *dev;
418 a5d2f727 Gerd Hoffmann
419 a5d2f727 Gerd Hoffmann
    bus = usb_bus_find(busnr);
420 a5d2f727 Gerd Hoffmann
    if (!bus)
421 a5d2f727 Gerd Hoffmann
        return -1;
422 a5d2f727 Gerd Hoffmann
423 72cf2d4f Blue Swirl
    QTAILQ_FOREACH(port, &bus->used, next) {
424 a5d2f727 Gerd Hoffmann
        if (port->dev->addr == addr)
425 a5d2f727 Gerd Hoffmann
            break;
426 a5d2f727 Gerd Hoffmann
    }
427 a5d2f727 Gerd Hoffmann
    if (!port)
428 a5d2f727 Gerd Hoffmann
        return -1;
429 a5d2f727 Gerd Hoffmann
    dev = port->dev;
430 a5d2f727 Gerd Hoffmann
431 a8e662b5 Gerd Hoffmann
    qdev_free(&dev->qdev);
432 a5d2f727 Gerd Hoffmann
    return 0;
433 a5d2f727 Gerd Hoffmann
}
434 a5d2f727 Gerd Hoffmann
435 a5d2f727 Gerd Hoffmann
static const char *usb_speed(unsigned int speed)
436 a5d2f727 Gerd Hoffmann
{
437 a5d2f727 Gerd Hoffmann
    static const char *txt[] = {
438 a5d2f727 Gerd Hoffmann
        [ USB_SPEED_LOW  ] = "1.5",
439 a5d2f727 Gerd Hoffmann
        [ USB_SPEED_FULL ] = "12",
440 a5d2f727 Gerd Hoffmann
        [ USB_SPEED_HIGH ] = "480",
441 290d26d2 Hans de Goede
        [ USB_SPEED_SUPER ] = "5000",
442 a5d2f727 Gerd Hoffmann
    };
443 a5d2f727 Gerd Hoffmann
    if (speed >= ARRAY_SIZE(txt))
444 a5d2f727 Gerd Hoffmann
        return "?";
445 a5d2f727 Gerd Hoffmann
    return txt[speed];
446 a5d2f727 Gerd Hoffmann
}
447 a5d2f727 Gerd Hoffmann
448 a5d2f727 Gerd Hoffmann
static void usb_bus_dev_print(Monitor *mon, DeviceState *qdev, int indent)
449 a5d2f727 Gerd Hoffmann
{
450 62aed765 Anthony Liguori
    USBDevice *dev = USB_DEVICE(qdev);
451 a5d2f727 Gerd Hoffmann
    USBBus *bus = usb_bus_from_device(dev);
452 a5d2f727 Gerd Hoffmann
453 c7a2196a Gerd Hoffmann
    monitor_printf(mon, "%*saddr %d.%d, port %s, speed %s, name %s%s\n",
454 66a6593a Gerd Hoffmann
                   indent, "", bus->busnr, dev->addr,
455 c7a2196a Gerd Hoffmann
                   dev->port ? dev->port->path : "-",
456 0fe6d12e Markus Armbruster
                   usb_speed(dev->speed), dev->product_desc,
457 66a6593a Gerd Hoffmann
                   dev->attached ? ", attached" : "");
458 a5d2f727 Gerd Hoffmann
}
459 a5d2f727 Gerd Hoffmann
460 c7a2196a Gerd Hoffmann
static char *usb_get_dev_path(DeviceState *qdev)
461 c7a2196a Gerd Hoffmann
{
462 62aed765 Anthony Liguori
    USBDevice *dev = USB_DEVICE(qdev);
463 7267c094 Anthony Liguori
    return g_strdup(dev->port->path);
464 c7a2196a Gerd Hoffmann
}
465 c7a2196a Gerd Hoffmann
466 70d31cb2 Gerd Hoffmann
static char *usb_get_fw_dev_path(DeviceState *qdev)
467 70d31cb2 Gerd Hoffmann
{
468 62aed765 Anthony Liguori
    USBDevice *dev = USB_DEVICE(qdev);
469 70d31cb2 Gerd Hoffmann
    char *fw_path, *in;
470 ea87e95f Blue Swirl
    ssize_t pos = 0, fw_len;
471 70d31cb2 Gerd Hoffmann
    long nr;
472 70d31cb2 Gerd Hoffmann
473 ea87e95f Blue Swirl
    fw_len = 32 + strlen(dev->port->path) * 6;
474 7267c094 Anthony Liguori
    fw_path = g_malloc(fw_len);
475 70d31cb2 Gerd Hoffmann
    in = dev->port->path;
476 ea87e95f Blue Swirl
    while (fw_len - pos > 0) {
477 70d31cb2 Gerd Hoffmann
        nr = strtol(in, &in, 10);
478 70d31cb2 Gerd Hoffmann
        if (in[0] == '.') {
479 70d31cb2 Gerd Hoffmann
            /* some hub between root port and device */
480 ea87e95f Blue Swirl
            pos += snprintf(fw_path + pos, fw_len - pos, "hub@%ld/", nr);
481 70d31cb2 Gerd Hoffmann
            in++;
482 70d31cb2 Gerd Hoffmann
        } else {
483 70d31cb2 Gerd Hoffmann
            /* the device itself */
484 ea87e95f Blue Swirl
            pos += snprintf(fw_path + pos, fw_len - pos, "%s@%ld",
485 ea87e95f Blue Swirl
                            qdev_fw_name(qdev), nr);
486 70d31cb2 Gerd Hoffmann
            break;
487 70d31cb2 Gerd Hoffmann
        }
488 70d31cb2 Gerd Hoffmann
    }
489 70d31cb2 Gerd Hoffmann
    return fw_path;
490 70d31cb2 Gerd Hoffmann
}
491 70d31cb2 Gerd Hoffmann
492 a5d2f727 Gerd Hoffmann
void usb_info(Monitor *mon)
493 a5d2f727 Gerd Hoffmann
{
494 a5d2f727 Gerd Hoffmann
    USBBus *bus;
495 a5d2f727 Gerd Hoffmann
    USBDevice *dev;
496 a5d2f727 Gerd Hoffmann
    USBPort *port;
497 a5d2f727 Gerd Hoffmann
498 72cf2d4f Blue Swirl
    if (QTAILQ_EMPTY(&busses)) {
499 a5d2f727 Gerd Hoffmann
        monitor_printf(mon, "USB support not enabled\n");
500 a5d2f727 Gerd Hoffmann
        return;
501 a5d2f727 Gerd Hoffmann
    }
502 a5d2f727 Gerd Hoffmann
503 72cf2d4f Blue Swirl
    QTAILQ_FOREACH(bus, &busses, next) {
504 72cf2d4f Blue Swirl
        QTAILQ_FOREACH(port, &bus->used, next) {
505 a5d2f727 Gerd Hoffmann
            dev = port->dev;
506 a5d2f727 Gerd Hoffmann
            if (!dev)
507 a5d2f727 Gerd Hoffmann
                continue;
508 c7a2196a Gerd Hoffmann
            monitor_printf(mon, "  Device %d.%d, Port %s, Speed %s Mb/s, Product %s\n",
509 c7a2196a Gerd Hoffmann
                           bus->busnr, dev->addr, port->path, usb_speed(dev->speed),
510 0fe6d12e Markus Armbruster
                           dev->product_desc);
511 a5d2f727 Gerd Hoffmann
        }
512 a5d2f727 Gerd Hoffmann
    }
513 a5d2f727 Gerd Hoffmann
}
514 a5d2f727 Gerd Hoffmann
515 0958b4cc Gerd Hoffmann
/* handle legacy -usbdevice cmd line option */
516 0958b4cc Gerd Hoffmann
USBDevice *usbdevice_create(const char *cmdline)
517 0958b4cc Gerd Hoffmann
{
518 0958b4cc Gerd Hoffmann
    USBBus *bus = usb_bus_find(-1 /* any */);
519 62aed765 Anthony Liguori
    LegacyUSBFactory *f = NULL;
520 62aed765 Anthony Liguori
    GSList *i;
521 702f3e0f Jan Kiszka
    char driver[32];
522 702f3e0f Jan Kiszka
    const char *params;
523 0958b4cc Gerd Hoffmann
    int len;
524 0958b4cc Gerd Hoffmann
525 0958b4cc Gerd Hoffmann
    params = strchr(cmdline,':');
526 0958b4cc Gerd Hoffmann
    if (params) {
527 0958b4cc Gerd Hoffmann
        params++;
528 0958b4cc Gerd Hoffmann
        len = params - cmdline;
529 0958b4cc Gerd Hoffmann
        if (len > sizeof(driver))
530 0958b4cc Gerd Hoffmann
            len = sizeof(driver);
531 0958b4cc Gerd Hoffmann
        pstrcpy(driver, len, cmdline);
532 0958b4cc Gerd Hoffmann
    } else {
533 702f3e0f Jan Kiszka
        params = "";
534 0958b4cc Gerd Hoffmann
        pstrcpy(driver, sizeof(driver), cmdline);
535 0958b4cc Gerd Hoffmann
    }
536 0958b4cc Gerd Hoffmann
537 62aed765 Anthony Liguori
    for (i = legacy_usb_factory; i; i = i->next) {
538 62aed765 Anthony Liguori
        f = i->data;
539 62aed765 Anthony Liguori
        if (strcmp(f->usbdevice_name, driver) == 0) {
540 62aed765 Anthony Liguori
            break;
541 62aed765 Anthony Liguori
        }
542 0958b4cc Gerd Hoffmann
    }
543 62aed765 Anthony Liguori
    if (i == NULL) {
544 0958b4cc Gerd Hoffmann
#if 0
545 0958b4cc Gerd Hoffmann
        /* no error because some drivers are not converted (yet) */
546 1ecda02b Markus Armbruster
        error_report("usbdevice %s not found", driver);
547 0958b4cc Gerd Hoffmann
#endif
548 0958b4cc Gerd Hoffmann
        return NULL;
549 0958b4cc Gerd Hoffmann
    }
550 0958b4cc Gerd Hoffmann
551 62aed765 Anthony Liguori
    if (!f->usbdevice_init) {
552 98f22dc1 TeLeMan
        if (*params) {
553 1ecda02b Markus Armbruster
            error_report("usbdevice %s accepts no params", driver);
554 0958b4cc Gerd Hoffmann
            return NULL;
555 0958b4cc Gerd Hoffmann
        }
556 62aed765 Anthony Liguori
        return usb_create_simple(bus, f->name);
557 0958b4cc Gerd Hoffmann
    }
558 3741715c Jan Kiszka
    return f->usbdevice_init(bus, params);
559 0958b4cc Gerd Hoffmann
}
560 62aed765 Anthony Liguori
561 39bffca2 Anthony Liguori
static void usb_device_class_init(ObjectClass *klass, void *data)
562 39bffca2 Anthony Liguori
{
563 39bffca2 Anthony Liguori
    DeviceClass *k = DEVICE_CLASS(klass);
564 39bffca2 Anthony Liguori
    k->bus_info = &usb_bus_info;
565 39bffca2 Anthony Liguori
    k->init     = usb_qdev_init;
566 39bffca2 Anthony Liguori
    k->unplug   = qdev_simple_unplug_cb;
567 39bffca2 Anthony Liguori
    k->exit     = usb_qdev_exit;
568 39bffca2 Anthony Liguori
}
569 39bffca2 Anthony Liguori
570 62aed765 Anthony Liguori
static TypeInfo usb_device_type_info = {
571 62aed765 Anthony Liguori
    .name = TYPE_USB_DEVICE,
572 62aed765 Anthony Liguori
    .parent = TYPE_DEVICE,
573 62aed765 Anthony Liguori
    .instance_size = sizeof(USBDevice),
574 62aed765 Anthony Liguori
    .abstract = true,
575 62aed765 Anthony Liguori
    .class_size = sizeof(USBDeviceClass),
576 39bffca2 Anthony Liguori
    .class_init = usb_device_class_init,
577 62aed765 Anthony Liguori
};
578 62aed765 Anthony Liguori
579 83f7d43a Andreas Färber
static void usb_register_types(void)
580 62aed765 Anthony Liguori
{
581 62aed765 Anthony Liguori
    type_register_static(&usb_device_type_info);
582 62aed765 Anthony Liguori
}
583 62aed765 Anthony Liguori
584 83f7d43a Andreas Färber
type_init(usb_register_types)