Statistics
| Branch: | Revision:

root / hw / usb-bus.c @ 1f51470d

History | View | Annotate | Download (14.9 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 62aed765 Anthony Liguori
    USBDevice *(*usbdevice_init)(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 ba02430f Anthony Liguori
                         USBDevice *(*usbdevice_init)(const char *params))
213 806b6024 Gerd Hoffmann
{
214 62aed765 Anthony Liguori
    if (usbdevice_name) {
215 62aed765 Anthony Liguori
        LegacyUSBFactory *f = g_malloc0(sizeof(*f));
216 ba02430f Anthony Liguori
        f->name = typename;
217 62aed765 Anthony Liguori
        f->usbdevice_name = usbdevice_name;
218 62aed765 Anthony Liguori
        f->usbdevice_init = usbdevice_init;
219 62aed765 Anthony Liguori
        legacy_usb_factory = g_slist_append(legacy_usb_factory, f);
220 806b6024 Gerd Hoffmann
    }
221 806b6024 Gerd Hoffmann
}
222 806b6024 Gerd Hoffmann
223 a5d2f727 Gerd Hoffmann
USBDevice *usb_create(USBBus *bus, const char *name)
224 806b6024 Gerd Hoffmann
{
225 806b6024 Gerd Hoffmann
    DeviceState *dev;
226 806b6024 Gerd Hoffmann
227 806b6024 Gerd Hoffmann
#if 1
228 806b6024 Gerd Hoffmann
    /* temporary stopgap until all usb is properly qdev-ified */
229 806b6024 Gerd Hoffmann
    if (!bus) {
230 806b6024 Gerd Hoffmann
        bus = usb_bus_find(-1);
231 806b6024 Gerd Hoffmann
        if (!bus)
232 806b6024 Gerd Hoffmann
            return NULL;
233 be62a2eb Markus Armbruster
        error_report("%s: no bus specified, using \"%s\" for \"%s\"",
234 806b6024 Gerd Hoffmann
                __FUNCTION__, bus->qbus.name, name);
235 806b6024 Gerd Hoffmann
    }
236 806b6024 Gerd Hoffmann
#endif
237 806b6024 Gerd Hoffmann
238 806b6024 Gerd Hoffmann
    dev = qdev_create(&bus->qbus, name);
239 62aed765 Anthony Liguori
    return USB_DEVICE(dev);
240 806b6024 Gerd Hoffmann
}
241 a5d2f727 Gerd Hoffmann
242 a5d2f727 Gerd Hoffmann
USBDevice *usb_create_simple(USBBus *bus, const char *name)
243 a5d2f727 Gerd Hoffmann
{
244 a5d2f727 Gerd Hoffmann
    USBDevice *dev = usb_create(bus, name);
245 2af2a1b8 Gerd Hoffmann
    int rc;
246 2af2a1b8 Gerd Hoffmann
247 d44168ff Paul Brook
    if (!dev) {
248 be62a2eb Markus Armbruster
        error_report("Failed to create USB device '%s'", name);
249 2af2a1b8 Gerd Hoffmann
        return NULL;
250 2af2a1b8 Gerd Hoffmann
    }
251 2af2a1b8 Gerd Hoffmann
    rc = qdev_init(&dev->qdev);
252 2af2a1b8 Gerd Hoffmann
    if (rc < 0) {
253 be62a2eb Markus Armbruster
        error_report("Failed to initialize USB device '%s'", name);
254 2af2a1b8 Gerd Hoffmann
        return NULL;
255 d44168ff Paul Brook
    }
256 a5d2f727 Gerd Hoffmann
    return dev;
257 a5d2f727 Gerd Hoffmann
}
258 a5d2f727 Gerd Hoffmann
259 090ac642 Hans de Goede
static void usb_fill_port(USBPort *port, void *opaque, int index,
260 090ac642 Hans de Goede
                          USBPortOps *ops, int speedmask)
261 a5d2f727 Gerd Hoffmann
{
262 a5d2f727 Gerd Hoffmann
    port->opaque = opaque;
263 a5d2f727 Gerd Hoffmann
    port->index = index;
264 0d86d2be Gerd Hoffmann
    port->ops = ops;
265 843d4e0c Gerd Hoffmann
    port->speedmask = speedmask;
266 3631e6c8 Hans de Goede
    usb_port_location(port, NULL, index + 1);
267 090ac642 Hans de Goede
}
268 090ac642 Hans de Goede
269 090ac642 Hans de Goede
void usb_register_port(USBBus *bus, USBPort *port, void *opaque, int index,
270 090ac642 Hans de Goede
                       USBPortOps *ops, int speedmask)
271 090ac642 Hans de Goede
{
272 090ac642 Hans de Goede
    usb_fill_port(port, opaque, index, ops, speedmask);
273 72cf2d4f Blue Swirl
    QTAILQ_INSERT_TAIL(&bus->free, port, next);
274 a5d2f727 Gerd Hoffmann
    bus->nfree++;
275 a5d2f727 Gerd Hoffmann
}
276 a5d2f727 Gerd Hoffmann
277 ae60fea9 Hans de Goede
int usb_register_companion(const char *masterbus, USBPort *ports[],
278 ae60fea9 Hans de Goede
                           uint32_t portcount, uint32_t firstport,
279 ae60fea9 Hans de Goede
                           void *opaque, USBPortOps *ops, int speedmask)
280 ae60fea9 Hans de Goede
{
281 ae60fea9 Hans de Goede
    USBBus *bus;
282 ae60fea9 Hans de Goede
    int i;
283 ae60fea9 Hans de Goede
284 ae60fea9 Hans de Goede
    QTAILQ_FOREACH(bus, &busses, next) {
285 ae60fea9 Hans de Goede
        if (strcmp(bus->qbus.name, masterbus) == 0) {
286 ae60fea9 Hans de Goede
            break;
287 ae60fea9 Hans de Goede
        }
288 ae60fea9 Hans de Goede
    }
289 ae60fea9 Hans de Goede
290 ae60fea9 Hans de Goede
    if (!bus || !bus->ops->register_companion) {
291 ae60fea9 Hans de Goede
        qerror_report(QERR_INVALID_PARAMETER_VALUE, "masterbus",
292 ae60fea9 Hans de Goede
                      "an USB masterbus");
293 ae60fea9 Hans de Goede
        if (bus) {
294 ae60fea9 Hans de Goede
            error_printf_unless_qmp(
295 ae60fea9 Hans de Goede
                "USB bus '%s' does not allow companion controllers\n",
296 ae60fea9 Hans de Goede
                masterbus);
297 ae60fea9 Hans de Goede
        }
298 ae60fea9 Hans de Goede
        return -1;
299 ae60fea9 Hans de Goede
    }
300 ae60fea9 Hans de Goede
301 ae60fea9 Hans de Goede
    for (i = 0; i < portcount; i++) {
302 ae60fea9 Hans de Goede
        usb_fill_port(ports[i], opaque, i, ops, speedmask);
303 ae60fea9 Hans de Goede
    }
304 ae60fea9 Hans de Goede
305 ae60fea9 Hans de Goede
    return bus->ops->register_companion(bus, ports, portcount, firstport);
306 ae60fea9 Hans de Goede
}
307 ae60fea9 Hans de Goede
308 c7a2196a Gerd Hoffmann
void usb_port_location(USBPort *downstream, USBPort *upstream, int portnr)
309 c7a2196a Gerd Hoffmann
{
310 c7a2196a Gerd Hoffmann
    if (upstream) {
311 c7a2196a Gerd Hoffmann
        snprintf(downstream->path, sizeof(downstream->path), "%s.%d",
312 c7a2196a Gerd Hoffmann
                 upstream->path, portnr);
313 c7a2196a Gerd Hoffmann
    } else {
314 c7a2196a Gerd Hoffmann
        snprintf(downstream->path, sizeof(downstream->path), "%d", portnr);
315 c7a2196a Gerd Hoffmann
    }
316 c7a2196a Gerd Hoffmann
}
317 c7a2196a Gerd Hoffmann
318 a8e662b5 Gerd Hoffmann
void usb_unregister_port(USBBus *bus, USBPort *port)
319 a8e662b5 Gerd Hoffmann
{
320 a8e662b5 Gerd Hoffmann
    if (port->dev)
321 a8e662b5 Gerd Hoffmann
        qdev_free(&port->dev->qdev);
322 a8e662b5 Gerd Hoffmann
    QTAILQ_REMOVE(&bus->free, port, next);
323 a8e662b5 Gerd Hoffmann
    bus->nfree--;
324 a8e662b5 Gerd Hoffmann
}
325 a8e662b5 Gerd Hoffmann
326 891fb2cd Gerd Hoffmann
int usb_claim_port(USBDevice *dev)
327 a5d2f727 Gerd Hoffmann
{
328 a5d2f727 Gerd Hoffmann
    USBBus *bus = usb_bus_from_device(dev);
329 a5d2f727 Gerd Hoffmann
    USBPort *port;
330 a5d2f727 Gerd Hoffmann
331 891fb2cd Gerd Hoffmann
    assert(dev->port == NULL);
332 891fb2cd Gerd Hoffmann
333 5f69076b Gerd Hoffmann
    if (dev->port_path) {
334 5f69076b Gerd Hoffmann
        QTAILQ_FOREACH(port, &bus->free, next) {
335 5f69076b Gerd Hoffmann
            if (strcmp(port->path, dev->port_path) == 0) {
336 5f69076b Gerd Hoffmann
                break;
337 5f69076b Gerd Hoffmann
            }
338 5f69076b Gerd Hoffmann
        }
339 5f69076b Gerd Hoffmann
        if (port == NULL) {
340 be62a2eb Markus Armbruster
            error_report("Error: usb port %s (bus %s) not found (in use?)",
341 891fb2cd Gerd Hoffmann
                         dev->port_path, bus->qbus.name);
342 fa19bf83 Hans de Goede
            return -1;
343 5f69076b Gerd Hoffmann
        }
344 5f69076b Gerd Hoffmann
    } else {
345 f79f2bfc Anthony Liguori
        if (bus->nfree == 1 && strcmp(object_get_typename(OBJECT(dev)), "usb-hub") != 0) {
346 891fb2cd Gerd Hoffmann
            /* Create a new hub and chain it on */
347 891fb2cd Gerd Hoffmann
            usb_create_simple(bus, "usb-hub");
348 891fb2cd Gerd Hoffmann
        }
349 891fb2cd Gerd Hoffmann
        if (bus->nfree == 0) {
350 891fb2cd Gerd Hoffmann
            error_report("Error: tried to attach usb device %s to a bus "
351 be62a2eb Markus Armbruster
                         "with no free ports", dev->product_desc);
352 891fb2cd Gerd Hoffmann
            return -1;
353 891fb2cd Gerd Hoffmann
        }
354 5f69076b Gerd Hoffmann
        port = QTAILQ_FIRST(&bus->free);
355 5f69076b Gerd Hoffmann
    }
356 891fb2cd Gerd Hoffmann
    trace_usb_port_claim(bus->busnr, port->path);
357 a5d2f727 Gerd Hoffmann
358 72cf2d4f Blue Swirl
    QTAILQ_REMOVE(&bus->free, port, next);
359 a5d2f727 Gerd Hoffmann
    bus->nfree--;
360 a5d2f727 Gerd Hoffmann
361 891fb2cd Gerd Hoffmann
    dev->port = port;
362 891fb2cd Gerd Hoffmann
    port->dev = dev;
363 a5d2f727 Gerd Hoffmann
364 72cf2d4f Blue Swirl
    QTAILQ_INSERT_TAIL(&bus->used, port, next);
365 a5d2f727 Gerd Hoffmann
    bus->nused++;
366 fa19bf83 Hans de Goede
    return 0;
367 a5d2f727 Gerd Hoffmann
}
368 a5d2f727 Gerd Hoffmann
369 891fb2cd Gerd Hoffmann
void usb_release_port(USBDevice *dev)
370 a5d2f727 Gerd Hoffmann
{
371 a5d2f727 Gerd Hoffmann
    USBBus *bus = usb_bus_from_device(dev);
372 891fb2cd Gerd Hoffmann
    USBPort *port = dev->port;
373 a5d2f727 Gerd Hoffmann
374 891fb2cd Gerd Hoffmann
    assert(port != NULL);
375 891fb2cd Gerd Hoffmann
    trace_usb_port_release(bus->busnr, port->path);
376 891fb2cd Gerd Hoffmann
377 891fb2cd Gerd Hoffmann
    QTAILQ_REMOVE(&bus->used, port, next);
378 891fb2cd Gerd Hoffmann
    bus->nused--;
379 891fb2cd Gerd Hoffmann
380 891fb2cd Gerd Hoffmann
    dev->port = NULL;
381 891fb2cd Gerd Hoffmann
    port->dev = NULL;
382 891fb2cd Gerd Hoffmann
383 891fb2cd Gerd Hoffmann
    QTAILQ_INSERT_TAIL(&bus->free, port, next);
384 891fb2cd Gerd Hoffmann
    bus->nfree++;
385 a5d2f727 Gerd Hoffmann
}
386 a5d2f727 Gerd Hoffmann
387 891fb2cd Gerd Hoffmann
int usb_device_attach(USBDevice *dev)
388 a8e662b5 Gerd Hoffmann
{
389 a8e662b5 Gerd Hoffmann
    USBBus *bus = usb_bus_from_device(dev);
390 891fb2cd Gerd Hoffmann
    USBPort *port = dev->port;
391 a8e662b5 Gerd Hoffmann
392 891fb2cd Gerd Hoffmann
    assert(port != NULL);
393 891fb2cd Gerd Hoffmann
    assert(!dev->attached);
394 891fb2cd Gerd Hoffmann
    trace_usb_port_attach(bus->busnr, port->path);
395 891fb2cd Gerd Hoffmann
396 891fb2cd Gerd Hoffmann
    if (!(port->speedmask & dev->speedmask)) {
397 891fb2cd Gerd Hoffmann
        error_report("Warning: speed mismatch trying to attach "
398 be62a2eb Markus Armbruster
                     "usb device %s to bus %s",
399 891fb2cd Gerd Hoffmann
                     dev->product_desc, bus->qbus.name);
400 a8e662b5 Gerd Hoffmann
        return -1;
401 a8e662b5 Gerd Hoffmann
    }
402 a8e662b5 Gerd Hoffmann
403 891fb2cd Gerd Hoffmann
    dev->attached++;
404 891fb2cd Gerd Hoffmann
    usb_attach(port);
405 a8e662b5 Gerd Hoffmann
406 891fb2cd Gerd Hoffmann
    return 0;
407 891fb2cd Gerd Hoffmann
}
408 891fb2cd Gerd Hoffmann
409 891fb2cd Gerd Hoffmann
int usb_device_detach(USBDevice *dev)
410 891fb2cd Gerd Hoffmann
{
411 891fb2cd Gerd Hoffmann
    USBBus *bus = usb_bus_from_device(dev);
412 891fb2cd Gerd Hoffmann
    USBPort *port = dev->port;
413 a8e662b5 Gerd Hoffmann
414 891fb2cd Gerd Hoffmann
    assert(port != NULL);
415 891fb2cd Gerd Hoffmann
    assert(dev->attached);
416 891fb2cd Gerd Hoffmann
    trace_usb_port_detach(bus->busnr, port->path);
417 a8e662b5 Gerd Hoffmann
418 891fb2cd Gerd Hoffmann
    usb_detach(port);
419 891fb2cd Gerd Hoffmann
    dev->attached--;
420 a8e662b5 Gerd Hoffmann
    return 0;
421 a8e662b5 Gerd Hoffmann
}
422 a8e662b5 Gerd Hoffmann
423 a5d2f727 Gerd Hoffmann
int usb_device_delete_addr(int busnr, int addr)
424 a5d2f727 Gerd Hoffmann
{
425 a5d2f727 Gerd Hoffmann
    USBBus *bus;
426 a5d2f727 Gerd Hoffmann
    USBPort *port;
427 a5d2f727 Gerd Hoffmann
    USBDevice *dev;
428 a5d2f727 Gerd Hoffmann
429 a5d2f727 Gerd Hoffmann
    bus = usb_bus_find(busnr);
430 a5d2f727 Gerd Hoffmann
    if (!bus)
431 a5d2f727 Gerd Hoffmann
        return -1;
432 a5d2f727 Gerd Hoffmann
433 72cf2d4f Blue Swirl
    QTAILQ_FOREACH(port, &bus->used, next) {
434 a5d2f727 Gerd Hoffmann
        if (port->dev->addr == addr)
435 a5d2f727 Gerd Hoffmann
            break;
436 a5d2f727 Gerd Hoffmann
    }
437 a5d2f727 Gerd Hoffmann
    if (!port)
438 a5d2f727 Gerd Hoffmann
        return -1;
439 a5d2f727 Gerd Hoffmann
    dev = port->dev;
440 a5d2f727 Gerd Hoffmann
441 a8e662b5 Gerd Hoffmann
    qdev_free(&dev->qdev);
442 a5d2f727 Gerd Hoffmann
    return 0;
443 a5d2f727 Gerd Hoffmann
}
444 a5d2f727 Gerd Hoffmann
445 a5d2f727 Gerd Hoffmann
static const char *usb_speed(unsigned int speed)
446 a5d2f727 Gerd Hoffmann
{
447 a5d2f727 Gerd Hoffmann
    static const char *txt[] = {
448 a5d2f727 Gerd Hoffmann
        [ USB_SPEED_LOW  ] = "1.5",
449 a5d2f727 Gerd Hoffmann
        [ USB_SPEED_FULL ] = "12",
450 a5d2f727 Gerd Hoffmann
        [ USB_SPEED_HIGH ] = "480",
451 290d26d2 Hans de Goede
        [ USB_SPEED_SUPER ] = "5000",
452 a5d2f727 Gerd Hoffmann
    };
453 a5d2f727 Gerd Hoffmann
    if (speed >= ARRAY_SIZE(txt))
454 a5d2f727 Gerd Hoffmann
        return "?";
455 a5d2f727 Gerd Hoffmann
    return txt[speed];
456 a5d2f727 Gerd Hoffmann
}
457 a5d2f727 Gerd Hoffmann
458 a5d2f727 Gerd Hoffmann
static void usb_bus_dev_print(Monitor *mon, DeviceState *qdev, int indent)
459 a5d2f727 Gerd Hoffmann
{
460 62aed765 Anthony Liguori
    USBDevice *dev = USB_DEVICE(qdev);
461 a5d2f727 Gerd Hoffmann
    USBBus *bus = usb_bus_from_device(dev);
462 a5d2f727 Gerd Hoffmann
463 c7a2196a Gerd Hoffmann
    monitor_printf(mon, "%*saddr %d.%d, port %s, speed %s, name %s%s\n",
464 66a6593a Gerd Hoffmann
                   indent, "", bus->busnr, dev->addr,
465 c7a2196a Gerd Hoffmann
                   dev->port ? dev->port->path : "-",
466 0fe6d12e Markus Armbruster
                   usb_speed(dev->speed), dev->product_desc,
467 66a6593a Gerd Hoffmann
                   dev->attached ? ", attached" : "");
468 a5d2f727 Gerd Hoffmann
}
469 a5d2f727 Gerd Hoffmann
470 c7a2196a Gerd Hoffmann
static char *usb_get_dev_path(DeviceState *qdev)
471 c7a2196a Gerd Hoffmann
{
472 62aed765 Anthony Liguori
    USBDevice *dev = USB_DEVICE(qdev);
473 7267c094 Anthony Liguori
    return g_strdup(dev->port->path);
474 c7a2196a Gerd Hoffmann
}
475 c7a2196a Gerd Hoffmann
476 70d31cb2 Gerd Hoffmann
static char *usb_get_fw_dev_path(DeviceState *qdev)
477 70d31cb2 Gerd Hoffmann
{
478 62aed765 Anthony Liguori
    USBDevice *dev = USB_DEVICE(qdev);
479 70d31cb2 Gerd Hoffmann
    char *fw_path, *in;
480 ea87e95f Blue Swirl
    ssize_t pos = 0, fw_len;
481 70d31cb2 Gerd Hoffmann
    long nr;
482 70d31cb2 Gerd Hoffmann
483 ea87e95f Blue Swirl
    fw_len = 32 + strlen(dev->port->path) * 6;
484 7267c094 Anthony Liguori
    fw_path = g_malloc(fw_len);
485 70d31cb2 Gerd Hoffmann
    in = dev->port->path;
486 ea87e95f Blue Swirl
    while (fw_len - pos > 0) {
487 70d31cb2 Gerd Hoffmann
        nr = strtol(in, &in, 10);
488 70d31cb2 Gerd Hoffmann
        if (in[0] == '.') {
489 70d31cb2 Gerd Hoffmann
            /* some hub between root port and device */
490 ea87e95f Blue Swirl
            pos += snprintf(fw_path + pos, fw_len - pos, "hub@%ld/", nr);
491 70d31cb2 Gerd Hoffmann
            in++;
492 70d31cb2 Gerd Hoffmann
        } else {
493 70d31cb2 Gerd Hoffmann
            /* the device itself */
494 ea87e95f Blue Swirl
            pos += snprintf(fw_path + pos, fw_len - pos, "%s@%ld",
495 ea87e95f Blue Swirl
                            qdev_fw_name(qdev), nr);
496 70d31cb2 Gerd Hoffmann
            break;
497 70d31cb2 Gerd Hoffmann
        }
498 70d31cb2 Gerd Hoffmann
    }
499 70d31cb2 Gerd Hoffmann
    return fw_path;
500 70d31cb2 Gerd Hoffmann
}
501 70d31cb2 Gerd Hoffmann
502 a5d2f727 Gerd Hoffmann
void usb_info(Monitor *mon)
503 a5d2f727 Gerd Hoffmann
{
504 a5d2f727 Gerd Hoffmann
    USBBus *bus;
505 a5d2f727 Gerd Hoffmann
    USBDevice *dev;
506 a5d2f727 Gerd Hoffmann
    USBPort *port;
507 a5d2f727 Gerd Hoffmann
508 72cf2d4f Blue Swirl
    if (QTAILQ_EMPTY(&busses)) {
509 a5d2f727 Gerd Hoffmann
        monitor_printf(mon, "USB support not enabled\n");
510 a5d2f727 Gerd Hoffmann
        return;
511 a5d2f727 Gerd Hoffmann
    }
512 a5d2f727 Gerd Hoffmann
513 72cf2d4f Blue Swirl
    QTAILQ_FOREACH(bus, &busses, next) {
514 72cf2d4f Blue Swirl
        QTAILQ_FOREACH(port, &bus->used, next) {
515 a5d2f727 Gerd Hoffmann
            dev = port->dev;
516 a5d2f727 Gerd Hoffmann
            if (!dev)
517 a5d2f727 Gerd Hoffmann
                continue;
518 c7a2196a Gerd Hoffmann
            monitor_printf(mon, "  Device %d.%d, Port %s, Speed %s Mb/s, Product %s\n",
519 c7a2196a Gerd Hoffmann
                           bus->busnr, dev->addr, port->path, usb_speed(dev->speed),
520 0fe6d12e Markus Armbruster
                           dev->product_desc);
521 a5d2f727 Gerd Hoffmann
        }
522 a5d2f727 Gerd Hoffmann
    }
523 a5d2f727 Gerd Hoffmann
}
524 a5d2f727 Gerd Hoffmann
525 0958b4cc Gerd Hoffmann
/* handle legacy -usbdevice cmd line option */
526 0958b4cc Gerd Hoffmann
USBDevice *usbdevice_create(const char *cmdline)
527 0958b4cc Gerd Hoffmann
{
528 0958b4cc Gerd Hoffmann
    USBBus *bus = usb_bus_find(-1 /* any */);
529 62aed765 Anthony Liguori
    LegacyUSBFactory *f = NULL;
530 62aed765 Anthony Liguori
    GSList *i;
531 702f3e0f Jan Kiszka
    char driver[32];
532 702f3e0f Jan Kiszka
    const char *params;
533 0958b4cc Gerd Hoffmann
    int len;
534 0958b4cc Gerd Hoffmann
535 0958b4cc Gerd Hoffmann
    params = strchr(cmdline,':');
536 0958b4cc Gerd Hoffmann
    if (params) {
537 0958b4cc Gerd Hoffmann
        params++;
538 0958b4cc Gerd Hoffmann
        len = params - cmdline;
539 0958b4cc Gerd Hoffmann
        if (len > sizeof(driver))
540 0958b4cc Gerd Hoffmann
            len = sizeof(driver);
541 0958b4cc Gerd Hoffmann
        pstrcpy(driver, len, cmdline);
542 0958b4cc Gerd Hoffmann
    } else {
543 702f3e0f Jan Kiszka
        params = "";
544 0958b4cc Gerd Hoffmann
        pstrcpy(driver, sizeof(driver), cmdline);
545 0958b4cc Gerd Hoffmann
    }
546 0958b4cc Gerd Hoffmann
547 62aed765 Anthony Liguori
    for (i = legacy_usb_factory; i; i = i->next) {
548 62aed765 Anthony Liguori
        f = i->data;
549 62aed765 Anthony Liguori
        if (strcmp(f->usbdevice_name, driver) == 0) {
550 62aed765 Anthony Liguori
            break;
551 62aed765 Anthony Liguori
        }
552 0958b4cc Gerd Hoffmann
    }
553 62aed765 Anthony Liguori
    if (i == NULL) {
554 0958b4cc Gerd Hoffmann
#if 0
555 0958b4cc Gerd Hoffmann
        /* no error because some drivers are not converted (yet) */
556 1ecda02b Markus Armbruster
        error_report("usbdevice %s not found", driver);
557 0958b4cc Gerd Hoffmann
#endif
558 0958b4cc Gerd Hoffmann
        return NULL;
559 0958b4cc Gerd Hoffmann
    }
560 0958b4cc Gerd Hoffmann
561 62aed765 Anthony Liguori
    if (!f->usbdevice_init) {
562 98f22dc1 TeLeMan
        if (*params) {
563 1ecda02b Markus Armbruster
            error_report("usbdevice %s accepts no params", driver);
564 0958b4cc Gerd Hoffmann
            return NULL;
565 0958b4cc Gerd Hoffmann
        }
566 62aed765 Anthony Liguori
        return usb_create_simple(bus, f->name);
567 0958b4cc Gerd Hoffmann
    }
568 62aed765 Anthony Liguori
    return f->usbdevice_init(params);
569 0958b4cc Gerd Hoffmann
}
570 62aed765 Anthony Liguori
571 39bffca2 Anthony Liguori
static void usb_device_class_init(ObjectClass *klass, void *data)
572 39bffca2 Anthony Liguori
{
573 39bffca2 Anthony Liguori
    DeviceClass *k = DEVICE_CLASS(klass);
574 39bffca2 Anthony Liguori
    k->bus_info = &usb_bus_info;
575 39bffca2 Anthony Liguori
    k->init     = usb_qdev_init;
576 39bffca2 Anthony Liguori
    k->unplug   = qdev_simple_unplug_cb;
577 39bffca2 Anthony Liguori
    k->exit     = usb_qdev_exit;
578 39bffca2 Anthony Liguori
}
579 39bffca2 Anthony Liguori
580 62aed765 Anthony Liguori
static TypeInfo usb_device_type_info = {
581 62aed765 Anthony Liguori
    .name = TYPE_USB_DEVICE,
582 62aed765 Anthony Liguori
    .parent = TYPE_DEVICE,
583 62aed765 Anthony Liguori
    .instance_size = sizeof(USBDevice),
584 62aed765 Anthony Liguori
    .abstract = true,
585 62aed765 Anthony Liguori
    .class_size = sizeof(USBDeviceClass),
586 39bffca2 Anthony Liguori
    .class_init = usb_device_class_init,
587 62aed765 Anthony Liguori
};
588 62aed765 Anthony Liguori
589 83f7d43a Andreas Färber
static void usb_register_types(void)
590 62aed765 Anthony Liguori
{
591 62aed765 Anthony Liguori
    type_register_static(&usb_device_type_info);
592 62aed765 Anthony Liguori
}
593 62aed765 Anthony Liguori
594 83f7d43a Andreas Färber
type_init(usb_register_types)