Fix sys-queue.h conflict for good
[qemu] / hw / usb-bus.c
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 QTAILQ_HEAD(, USBBus) busses = QTAILQ_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     QTAILQ_INIT(&bus->free);
24     QTAILQ_INIT(&bus->used);
25     QTAILQ_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 QTAILQ_FIRST(&busses);
35     QTAILQ_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     QTAILQ_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 = QTAILQ_FIRST(&bus->free);
120     QTAILQ_REMOVE(&bus->free, port, next);
121     bus->nfree--;
122
123     usb_attach(port, dev);
124
125     QTAILQ_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     QTAILQ_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     QTAILQ_REMOVE(&bus->used, port, next);
161     bus->nused--;
162
163     usb_attach(port, NULL);
164     dev->info->handle_destroy(dev);
165
166     QTAILQ_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 (QTAILQ_EMPTY(&busses)) {
200         monitor_printf(mon, "USB support not enabled\n");
201         return;
202     }
203
204     QTAILQ_FOREACH(bus, &busses, next) {
205         QTAILQ_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