Statistics
| Branch: | Revision:

root / hw / usb-hub.c @ 3d78499a

History | View | Annotate | Download (16.5 kB)

1 72899afc bellard
/*
2 72899afc bellard
 * QEMU USB HUB emulation
3 72899afc bellard
 *
4 72899afc bellard
 * Copyright (c) 2005 Fabrice Bellard
5 5fafdf24 ths
 *
6 72899afc bellard
 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 72899afc bellard
 * of this software and associated documentation files (the "Software"), to deal
8 72899afc bellard
 * in the Software without restriction, including without limitation the rights
9 72899afc bellard
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 72899afc bellard
 * copies of the Software, and to permit persons to whom the Software is
11 72899afc bellard
 * furnished to do so, subject to the following conditions:
12 72899afc bellard
 *
13 72899afc bellard
 * The above copyright notice and this permission notice shall be included in
14 72899afc bellard
 * all copies or substantial portions of the Software.
15 72899afc bellard
 *
16 72899afc bellard
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 72899afc bellard
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 72899afc bellard
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 72899afc bellard
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 72899afc bellard
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 72899afc bellard
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 72899afc bellard
 * THE SOFTWARE.
23 72899afc bellard
 */
24 87ecb68b pbrook
#include "qemu-common.h"
25 87ecb68b pbrook
#include "usb.h"
26 72899afc bellard
27 72899afc bellard
//#define DEBUG
28 72899afc bellard
29 72899afc bellard
#define MAX_PORTS 8
30 72899afc bellard
31 72899afc bellard
typedef struct USBHubPort {
32 72899afc bellard
    USBPort port;
33 72899afc bellard
    uint16_t wPortStatus;
34 72899afc bellard
    uint16_t wPortChange;
35 72899afc bellard
} USBHubPort;
36 72899afc bellard
37 72899afc bellard
typedef struct USBHubState {
38 72899afc bellard
    USBDevice dev;
39 72899afc bellard
    int nb_ports;
40 72899afc bellard
    USBHubPort ports[MAX_PORTS];
41 72899afc bellard
} USBHubState;
42 72899afc bellard
43 72899afc bellard
#define ClearHubFeature                (0x2000 | USB_REQ_CLEAR_FEATURE)
44 72899afc bellard
#define ClearPortFeature        (0x2300 | USB_REQ_CLEAR_FEATURE)
45 72899afc bellard
#define GetHubDescriptor        (0xa000 | USB_REQ_GET_DESCRIPTOR)
46 72899afc bellard
#define GetHubStatus                (0xa000 | USB_REQ_GET_STATUS)
47 72899afc bellard
#define GetPortStatus                (0xa300 | USB_REQ_GET_STATUS)
48 72899afc bellard
#define SetHubFeature                (0x2000 | USB_REQ_SET_FEATURE)
49 72899afc bellard
#define SetPortFeature                (0x2300 | USB_REQ_SET_FEATURE)
50 72899afc bellard
51 72899afc bellard
#define PORT_STAT_CONNECTION        0x0001
52 72899afc bellard
#define PORT_STAT_ENABLE        0x0002
53 72899afc bellard
#define PORT_STAT_SUSPEND        0x0004
54 72899afc bellard
#define PORT_STAT_OVERCURRENT        0x0008
55 72899afc bellard
#define PORT_STAT_RESET                0x0010
56 72899afc bellard
#define PORT_STAT_POWER                0x0100
57 72899afc bellard
#define PORT_STAT_LOW_SPEED        0x0200
58 72899afc bellard
#define PORT_STAT_HIGH_SPEED    0x0400
59 72899afc bellard
#define PORT_STAT_TEST          0x0800
60 72899afc bellard
#define PORT_STAT_INDICATOR     0x1000
61 72899afc bellard
62 72899afc bellard
#define PORT_STAT_C_CONNECTION        0x0001
63 72899afc bellard
#define PORT_STAT_C_ENABLE        0x0002
64 72899afc bellard
#define PORT_STAT_C_SUSPEND        0x0004
65 72899afc bellard
#define PORT_STAT_C_OVERCURRENT        0x0008
66 72899afc bellard
#define PORT_STAT_C_RESET        0x0010
67 72899afc bellard
68 72899afc bellard
#define PORT_CONNECTION                0
69 72899afc bellard
#define PORT_ENABLE                1
70 72899afc bellard
#define PORT_SUSPEND                2
71 72899afc bellard
#define PORT_OVERCURRENT        3
72 72899afc bellard
#define PORT_RESET                4
73 72899afc bellard
#define PORT_POWER                8
74 72899afc bellard
#define PORT_LOWSPEED                9
75 72899afc bellard
#define PORT_HIGHSPEED                10
76 72899afc bellard
#define PORT_C_CONNECTION        16
77 72899afc bellard
#define PORT_C_ENABLE                17
78 72899afc bellard
#define PORT_C_SUSPEND                18
79 72899afc bellard
#define PORT_C_OVERCURRENT        19
80 72899afc bellard
#define PORT_C_RESET                20
81 72899afc bellard
#define PORT_TEST               21
82 72899afc bellard
#define PORT_INDICATOR          22
83 72899afc bellard
84 72899afc bellard
/* same as Linux kernel root hubs */
85 72899afc bellard
86 72899afc bellard
static const uint8_t qemu_hub_dev_descriptor[] = {
87 72899afc bellard
        0x12,       /*  u8 bLength; */
88 72899afc bellard
        0x01,       /*  u8 bDescriptorType; Device */
89 72899afc bellard
        0x10, 0x01, /*  u16 bcdUSB; v1.1 */
90 72899afc bellard
91 72899afc bellard
        0x09,            /*  u8  bDeviceClass; HUB_CLASSCODE */
92 72899afc bellard
        0x00,            /*  u8  bDeviceSubClass; */
93 72899afc bellard
        0x00,       /*  u8  bDeviceProtocol; [ low/full speeds only ] */
94 72899afc bellard
        0x08,       /*  u8  bMaxPacketSize0; 8 Bytes */
95 72899afc bellard
96 72899afc bellard
        0x00, 0x00, /*  u16 idVendor; */
97 72899afc bellard
         0x00, 0x00, /*  u16 idProduct; */
98 72899afc bellard
        0x01, 0x01, /*  u16 bcdDevice */
99 72899afc bellard
100 72899afc bellard
        0x03,       /*  u8  iManufacturer; */
101 72899afc bellard
        0x02,       /*  u8  iProduct; */
102 72899afc bellard
        0x01,       /*  u8  iSerialNumber; */
103 72899afc bellard
        0x01        /*  u8  bNumConfigurations; */
104 72899afc bellard
};
105 72899afc bellard
106 72899afc bellard
/* XXX: patch interrupt size */
107 72899afc bellard
static const uint8_t qemu_hub_config_descriptor[] = {
108 72899afc bellard
109 72899afc bellard
        /* one configuration */
110 72899afc bellard
        0x09,       /*  u8  bLength; */
111 72899afc bellard
        0x02,       /*  u8  bDescriptorType; Configuration */
112 72899afc bellard
        0x19, 0x00, /*  u16 wTotalLength; */
113 72899afc bellard
        0x01,       /*  u8  bNumInterfaces; (1) */
114 72899afc bellard
        0x01,       /*  u8  bConfigurationValue; */
115 72899afc bellard
        0x00,       /*  u8  iConfiguration; */
116 659139d7 Riku Voipio
        0xe0,       /*  u8  bmAttributes;
117 72899afc bellard
                                 Bit 7: must be set,
118 72899afc bellard
                                     6: Self-powered,
119 72899afc bellard
                                     5: Remote wakeup,
120 72899afc bellard
                                     4..0: resvd */
121 72899afc bellard
        0x00,       /*  u8  MaxPower; */
122 3b46e624 ths
123 72899afc bellard
        /* USB 1.1:
124 72899afc bellard
         * USB 2.0, single TT organization (mandatory):
125 72899afc bellard
         *        one interface, protocol 0
126 72899afc bellard
         *
127 72899afc bellard
         * USB 2.0, multiple TT organization (optional):
128 72899afc bellard
         *        two interfaces, protocols 1 (like single TT)
129 72899afc bellard
         *        and 2 (multiple TT mode) ... config is
130 72899afc bellard
         *        sometimes settable
131 72899afc bellard
         *        NOT IMPLEMENTED
132 72899afc bellard
         */
133 72899afc bellard
134 72899afc bellard
        /* one interface */
135 72899afc bellard
        0x09,       /*  u8  if_bLength; */
136 72899afc bellard
        0x04,       /*  u8  if_bDescriptorType; Interface */
137 72899afc bellard
        0x00,       /*  u8  if_bInterfaceNumber; */
138 72899afc bellard
        0x00,       /*  u8  if_bAlternateSetting; */
139 72899afc bellard
        0x01,       /*  u8  if_bNumEndpoints; */
140 72899afc bellard
        0x09,       /*  u8  if_bInterfaceClass; HUB_CLASSCODE */
141 72899afc bellard
        0x00,       /*  u8  if_bInterfaceSubClass; */
142 72899afc bellard
        0x00,       /*  u8  if_bInterfaceProtocol; [usb1.1 or single tt] */
143 72899afc bellard
        0x00,       /*  u8  if_iInterface; */
144 3b46e624 ths
145 72899afc bellard
        /* one endpoint (status change endpoint) */
146 72899afc bellard
        0x07,       /*  u8  ep_bLength; */
147 72899afc bellard
        0x05,       /*  u8  ep_bDescriptorType; Endpoint */
148 72899afc bellard
        0x81,       /*  u8  ep_bEndpointAddress; IN Endpoint 1 */
149 72899afc bellard
         0x03,       /*  u8  ep_bmAttributes; Interrupt */
150 72899afc bellard
         0x02, 0x00, /*  u16 ep_wMaxPacketSize; 1 + (MAX_ROOT_PORTS / 8) */
151 72899afc bellard
        0xff        /*  u8  ep_bInterval; (255ms -- usb 2.0 spec) */
152 72899afc bellard
};
153 72899afc bellard
154 72899afc bellard
static const uint8_t qemu_hub_hub_descriptor[] =
155 72899afc bellard
{
156 67f36560 bellard
        0x00,                        /*  u8  bLength; patched in later */
157 72899afc bellard
        0x29,                        /*  u8  bDescriptorType; Hub-descriptor */
158 72899afc bellard
        0x00,                        /*  u8  bNbrPorts; (patched later) */
159 72899afc bellard
        0x0a,                        /* u16  wHubCharacteristics; */
160 72899afc bellard
        0x00,                        /*   (per-port OC, no power switching) */
161 72899afc bellard
        0x01,                        /*  u8  bPwrOn2pwrGood; 2ms */
162 985d1742 bellard
        0x00                        /*  u8  bHubContrCurrent; 0 mA */
163 985d1742 bellard
164 985d1742 bellard
        /* DeviceRemovable and PortPwrCtrlMask patched in later */
165 72899afc bellard
};
166 72899afc bellard
167 72899afc bellard
static void usb_hub_attach(USBPort *port1, USBDevice *dev)
168 72899afc bellard
{
169 72899afc bellard
    USBHubState *s = port1->opaque;
170 72899afc bellard
    USBHubPort *port = &s->ports[port1->index];
171 3b46e624 ths
172 72899afc bellard
    if (dev) {
173 72899afc bellard
        if (port->port.dev)
174 72899afc bellard
            usb_attach(port1, NULL);
175 3b46e624 ths
176 72899afc bellard
        port->wPortStatus |= PORT_STAT_CONNECTION;
177 72899afc bellard
        port->wPortChange |= PORT_STAT_C_CONNECTION;
178 72899afc bellard
        if (dev->speed == USB_SPEED_LOW)
179 72899afc bellard
            port->wPortStatus |= PORT_STAT_LOW_SPEED;
180 72899afc bellard
        else
181 72899afc bellard
            port->wPortStatus &= ~PORT_STAT_LOW_SPEED;
182 72899afc bellard
        port->port.dev = dev;
183 0d92ed30 pbrook
        /* send the attach message */
184 4d611c9a pbrook
        usb_send_msg(dev, USB_MSG_ATTACH);
185 72899afc bellard
    } else {
186 72899afc bellard
        dev = port->port.dev;
187 72899afc bellard
        if (dev) {
188 72899afc bellard
            port->wPortStatus &= ~PORT_STAT_CONNECTION;
189 72899afc bellard
            port->wPortChange |= PORT_STAT_C_CONNECTION;
190 72899afc bellard
            if (port->wPortStatus & PORT_STAT_ENABLE) {
191 72899afc bellard
                port->wPortStatus &= ~PORT_STAT_ENABLE;
192 72899afc bellard
                port->wPortChange |= PORT_STAT_C_ENABLE;
193 72899afc bellard
            }
194 0d92ed30 pbrook
            /* send the detach message */
195 4d611c9a pbrook
            usb_send_msg(dev, USB_MSG_DETACH);
196 72899afc bellard
            port->port.dev = NULL;
197 72899afc bellard
        }
198 72899afc bellard
    }
199 72899afc bellard
}
200 72899afc bellard
201 059809e4 bellard
static void usb_hub_handle_reset(USBDevice *dev)
202 72899afc bellard
{
203 72899afc bellard
    /* XXX: do it */
204 72899afc bellard
}
205 72899afc bellard
206 72899afc bellard
static int usb_hub_handle_control(USBDevice *dev, int request, int value,
207 72899afc bellard
                                  int index, int length, uint8_t *data)
208 72899afc bellard
{
209 72899afc bellard
    USBHubState *s = (USBHubState *)dev;
210 72899afc bellard
    int ret;
211 72899afc bellard
212 72899afc bellard
    switch(request) {
213 72899afc bellard
    case DeviceRequest | USB_REQ_GET_STATUS:
214 72899afc bellard
        data[0] = (1 << USB_DEVICE_SELF_POWERED) |
215 72899afc bellard
            (dev->remote_wakeup << USB_DEVICE_REMOTE_WAKEUP);
216 72899afc bellard
        data[1] = 0x00;
217 72899afc bellard
        ret = 2;
218 72899afc bellard
        break;
219 72899afc bellard
    case DeviceOutRequest | USB_REQ_CLEAR_FEATURE:
220 72899afc bellard
        if (value == USB_DEVICE_REMOTE_WAKEUP) {
221 72899afc bellard
            dev->remote_wakeup = 0;
222 72899afc bellard
        } else {
223 72899afc bellard
            goto fail;
224 72899afc bellard
        }
225 72899afc bellard
        ret = 0;
226 72899afc bellard
        break;
227 985d1742 bellard
    case EndpointOutRequest | USB_REQ_CLEAR_FEATURE:
228 985d1742 bellard
        if (value == 0 && index != 0x81) { /* clear ep halt */
229 985d1742 bellard
            goto fail;
230 985d1742 bellard
        }
231 985d1742 bellard
        ret = 0;
232 985d1742 bellard
        break;
233 72899afc bellard
    case DeviceOutRequest | USB_REQ_SET_FEATURE:
234 72899afc bellard
        if (value == USB_DEVICE_REMOTE_WAKEUP) {
235 72899afc bellard
            dev->remote_wakeup = 1;
236 72899afc bellard
        } else {
237 72899afc bellard
            goto fail;
238 72899afc bellard
        }
239 72899afc bellard
        ret = 0;
240 72899afc bellard
        break;
241 72899afc bellard
    case DeviceOutRequest | USB_REQ_SET_ADDRESS:
242 72899afc bellard
        dev->addr = value;
243 72899afc bellard
        ret = 0;
244 72899afc bellard
        break;
245 72899afc bellard
    case DeviceRequest | USB_REQ_GET_DESCRIPTOR:
246 72899afc bellard
        switch(value >> 8) {
247 72899afc bellard
        case USB_DT_DEVICE:
248 5fafdf24 ths
            memcpy(data, qemu_hub_dev_descriptor,
249 72899afc bellard
                   sizeof(qemu_hub_dev_descriptor));
250 72899afc bellard
            ret = sizeof(qemu_hub_dev_descriptor);
251 72899afc bellard
            break;
252 72899afc bellard
        case USB_DT_CONFIG:
253 5fafdf24 ths
            memcpy(data, qemu_hub_config_descriptor,
254 72899afc bellard
                   sizeof(qemu_hub_config_descriptor));
255 985d1742 bellard
256 985d1742 bellard
            /* status change endpoint size based on number
257 985d1742 bellard
             * of ports */
258 985d1742 bellard
            data[22] = (s->nb_ports + 1 + 7) / 8;
259 985d1742 bellard
260 72899afc bellard
            ret = sizeof(qemu_hub_config_descriptor);
261 72899afc bellard
            break;
262 72899afc bellard
        case USB_DT_STRING:
263 72899afc bellard
            switch(value & 0xff) {
264 72899afc bellard
            case 0:
265 72899afc bellard
                /* language ids */
266 72899afc bellard
                data[0] = 4;
267 72899afc bellard
                data[1] = 3;
268 72899afc bellard
                data[2] = 0x09;
269 72899afc bellard
                data[3] = 0x04;
270 72899afc bellard
                ret = 4;
271 72899afc bellard
                break;
272 72899afc bellard
            case 1:
273 72899afc bellard
                /* serial number */
274 72899afc bellard
                ret = set_usb_string(data, "314159");
275 72899afc bellard
                break;
276 72899afc bellard
            case 2:
277 72899afc bellard
                /* product description */
278 72899afc bellard
                ret = set_usb_string(data, "QEMU USB Hub");
279 72899afc bellard
                break;
280 72899afc bellard
            case 3:
281 72899afc bellard
                /* vendor description */
282 72899afc bellard
                ret = set_usb_string(data, "QEMU " QEMU_VERSION);
283 72899afc bellard
                break;
284 72899afc bellard
            default:
285 72899afc bellard
                goto fail;
286 72899afc bellard
            }
287 72899afc bellard
            break;
288 72899afc bellard
        default:
289 72899afc bellard
            goto fail;
290 72899afc bellard
        }
291 72899afc bellard
        break;
292 72899afc bellard
    case DeviceRequest | USB_REQ_GET_CONFIGURATION:
293 72899afc bellard
        data[0] = 1;
294 72899afc bellard
        ret = 1;
295 72899afc bellard
        break;
296 72899afc bellard
    case DeviceOutRequest | USB_REQ_SET_CONFIGURATION:
297 72899afc bellard
        ret = 0;
298 72899afc bellard
        break;
299 72899afc bellard
    case DeviceRequest | USB_REQ_GET_INTERFACE:
300 72899afc bellard
        data[0] = 0;
301 72899afc bellard
        ret = 1;
302 72899afc bellard
        break;
303 72899afc bellard
    case DeviceOutRequest | USB_REQ_SET_INTERFACE:
304 72899afc bellard
        ret = 0;
305 72899afc bellard
        break;
306 72899afc bellard
        /* usb specific requests */
307 72899afc bellard
    case GetHubStatus:
308 72899afc bellard
        data[0] = 0;
309 72899afc bellard
        data[1] = 0;
310 72899afc bellard
        data[2] = 0;
311 72899afc bellard
        data[3] = 0;
312 72899afc bellard
        ret = 4;
313 72899afc bellard
        break;
314 72899afc bellard
    case GetPortStatus:
315 72899afc bellard
        {
316 72899afc bellard
            unsigned int n = index - 1;
317 72899afc bellard
            USBHubPort *port;
318 72899afc bellard
            if (n >= s->nb_ports)
319 72899afc bellard
                goto fail;
320 72899afc bellard
            port = &s->ports[n];
321 72899afc bellard
            data[0] = port->wPortStatus;
322 72899afc bellard
            data[1] = port->wPortStatus >> 8;
323 72899afc bellard
            data[2] = port->wPortChange;
324 72899afc bellard
            data[3] = port->wPortChange >> 8;
325 72899afc bellard
            ret = 4;
326 72899afc bellard
        }
327 72899afc bellard
        break;
328 72899afc bellard
    case SetHubFeature:
329 72899afc bellard
    case ClearHubFeature:
330 72899afc bellard
        if (value == 0 || value == 1) {
331 72899afc bellard
        } else {
332 72899afc bellard
            goto fail;
333 72899afc bellard
        }
334 72899afc bellard
        ret = 0;
335 72899afc bellard
        break;
336 72899afc bellard
    case SetPortFeature:
337 72899afc bellard
        {
338 72899afc bellard
            unsigned int n = index - 1;
339 72899afc bellard
            USBHubPort *port;
340 72899afc bellard
            USBDevice *dev;
341 72899afc bellard
            if (n >= s->nb_ports)
342 72899afc bellard
                goto fail;
343 72899afc bellard
            port = &s->ports[n];
344 72899afc bellard
            dev = port->port.dev;
345 72899afc bellard
            switch(value) {
346 72899afc bellard
            case PORT_SUSPEND:
347 72899afc bellard
                port->wPortStatus |= PORT_STAT_SUSPEND;
348 72899afc bellard
                break;
349 72899afc bellard
            case PORT_RESET:
350 72899afc bellard
                if (dev) {
351 4d611c9a pbrook
                    usb_send_msg(dev, USB_MSG_RESET);
352 72899afc bellard
                    port->wPortChange |= PORT_STAT_C_RESET;
353 72899afc bellard
                    /* set enable bit */
354 72899afc bellard
                    port->wPortStatus |= PORT_STAT_ENABLE;
355 72899afc bellard
                }
356 72899afc bellard
                break;
357 72899afc bellard
            case PORT_POWER:
358 72899afc bellard
                break;
359 72899afc bellard
            default:
360 72899afc bellard
                goto fail;
361 72899afc bellard
            }
362 72899afc bellard
            ret = 0;
363 72899afc bellard
        }
364 72899afc bellard
        break;
365 72899afc bellard
    case ClearPortFeature:
366 72899afc bellard
        {
367 72899afc bellard
            unsigned int n = index - 1;
368 72899afc bellard
            USBHubPort *port;
369 d4c4e6fd Blue Swirl
370 72899afc bellard
            if (n >= s->nb_ports)
371 72899afc bellard
                goto fail;
372 72899afc bellard
            port = &s->ports[n];
373 72899afc bellard
            switch(value) {
374 72899afc bellard
            case PORT_ENABLE:
375 72899afc bellard
                port->wPortStatus &= ~PORT_STAT_ENABLE;
376 72899afc bellard
                break;
377 72899afc bellard
            case PORT_C_ENABLE:
378 72899afc bellard
                port->wPortChange &= ~PORT_STAT_C_ENABLE;
379 72899afc bellard
                break;
380 72899afc bellard
            case PORT_SUSPEND:
381 72899afc bellard
                port->wPortStatus &= ~PORT_STAT_SUSPEND;
382 72899afc bellard
                break;
383 72899afc bellard
            case PORT_C_SUSPEND:
384 72899afc bellard
                port->wPortChange &= ~PORT_STAT_C_SUSPEND;
385 72899afc bellard
                break;
386 72899afc bellard
            case PORT_C_CONNECTION:
387 72899afc bellard
                port->wPortChange &= ~PORT_STAT_C_CONNECTION;
388 72899afc bellard
                break;
389 72899afc bellard
            case PORT_C_OVERCURRENT:
390 72899afc bellard
                port->wPortChange &= ~PORT_STAT_C_OVERCURRENT;
391 72899afc bellard
                break;
392 72899afc bellard
            case PORT_C_RESET:
393 72899afc bellard
                port->wPortChange &= ~PORT_STAT_C_RESET;
394 72899afc bellard
                break;
395 72899afc bellard
            default:
396 72899afc bellard
                goto fail;
397 72899afc bellard
            }
398 72899afc bellard
            ret = 0;
399 72899afc bellard
        }
400 72899afc bellard
        break;
401 72899afc bellard
    case GetHubDescriptor:
402 985d1742 bellard
        {
403 985d1742 bellard
            unsigned int n, limit, var_hub_size = 0;
404 5fafdf24 ths
            memcpy(data, qemu_hub_hub_descriptor,
405 985d1742 bellard
                   sizeof(qemu_hub_hub_descriptor));
406 985d1742 bellard
            data[2] = s->nb_ports;
407 985d1742 bellard
408 985d1742 bellard
            /* fill DeviceRemovable bits */
409 985d1742 bellard
            limit = ((s->nb_ports + 1 + 7) / 8) + 7;
410 985d1742 bellard
            for (n = 7; n < limit; n++) {
411 985d1742 bellard
                data[n] = 0x00;
412 985d1742 bellard
                var_hub_size++;
413 985d1742 bellard
            }
414 985d1742 bellard
415 985d1742 bellard
            /* fill PortPwrCtrlMask bits */
416 985d1742 bellard
            limit = limit + ((s->nb_ports + 7) / 8);
417 985d1742 bellard
            for (;n < limit; n++) {
418 985d1742 bellard
                data[n] = 0xff;
419 985d1742 bellard
                var_hub_size++;
420 985d1742 bellard
            }
421 985d1742 bellard
422 985d1742 bellard
            ret = sizeof(qemu_hub_hub_descriptor) + var_hub_size;
423 67f36560 bellard
            data[0] = ret;
424 985d1742 bellard
            break;
425 985d1742 bellard
        }
426 72899afc bellard
    default:
427 72899afc bellard
    fail:
428 72899afc bellard
        ret = USB_RET_STALL;
429 72899afc bellard
        break;
430 72899afc bellard
    }
431 72899afc bellard
    return ret;
432 72899afc bellard
}
433 72899afc bellard
434 4d611c9a pbrook
static int usb_hub_handle_data(USBDevice *dev, USBPacket *p)
435 72899afc bellard
{
436 72899afc bellard
    USBHubState *s = (USBHubState *)dev;
437 72899afc bellard
    int ret;
438 72899afc bellard
439 4d611c9a pbrook
    switch(p->pid) {
440 72899afc bellard
    case USB_TOKEN_IN:
441 4d611c9a pbrook
        if (p->devep == 1) {
442 72899afc bellard
            USBHubPort *port;
443 72899afc bellard
            unsigned int status;
444 72899afc bellard
            int i, n;
445 72899afc bellard
            n = (s->nb_ports + 1 + 7) / 8;
446 4d611c9a pbrook
            if (p->len == 1) { /* FreeBSD workaround */
447 985d1742 bellard
                n = 1;
448 4d611c9a pbrook
            } else if (n > p->len) {
449 72899afc bellard
                return USB_RET_BABBLE;
450 985d1742 bellard
            }
451 72899afc bellard
            status = 0;
452 72899afc bellard
            for(i = 0; i < s->nb_ports; i++) {
453 72899afc bellard
                port = &s->ports[i];
454 72899afc bellard
                if (port->wPortChange)
455 72899afc bellard
                    status |= (1 << (i + 1));
456 72899afc bellard
            }
457 72899afc bellard
            if (status != 0) {
458 72899afc bellard
                for(i = 0; i < n; i++) {
459 4d611c9a pbrook
                    p->data[i] = status >> (8 * i);
460 72899afc bellard
                }
461 72899afc bellard
                ret = n;
462 72899afc bellard
            } else {
463 985d1742 bellard
                ret = USB_RET_NAK; /* usb11 11.13.1 */
464 72899afc bellard
            }
465 72899afc bellard
        } else {
466 72899afc bellard
            goto fail;
467 72899afc bellard
        }
468 72899afc bellard
        break;
469 72899afc bellard
    case USB_TOKEN_OUT:
470 72899afc bellard
    default:
471 72899afc bellard
    fail:
472 72899afc bellard
        ret = USB_RET_STALL;
473 72899afc bellard
        break;
474 72899afc bellard
    }
475 72899afc bellard
    return ret;
476 72899afc bellard
}
477 72899afc bellard
478 4d611c9a pbrook
static int usb_hub_broadcast_packet(USBHubState *s, USBPacket *p)
479 72899afc bellard
{
480 72899afc bellard
    USBHubPort *port;
481 72899afc bellard
    USBDevice *dev;
482 72899afc bellard
    int i, ret;
483 72899afc bellard
484 72899afc bellard
    for(i = 0; i < s->nb_ports; i++) {
485 72899afc bellard
        port = &s->ports[i];
486 72899afc bellard
        dev = port->port.dev;
487 72899afc bellard
        if (dev && (port->wPortStatus & PORT_STAT_ENABLE)) {
488 806b6024 Gerd Hoffmann
            ret = dev->info->handle_packet(dev, p);
489 72899afc bellard
            if (ret != USB_RET_NODEV) {
490 72899afc bellard
                return ret;
491 72899afc bellard
            }
492 72899afc bellard
        }
493 72899afc bellard
    }
494 72899afc bellard
    return USB_RET_NODEV;
495 72899afc bellard
}
496 72899afc bellard
497 4d611c9a pbrook
static int usb_hub_handle_packet(USBDevice *dev, USBPacket *p)
498 72899afc bellard
{
499 72899afc bellard
    USBHubState *s = (USBHubState *)dev;
500 72899afc bellard
501 72899afc bellard
#if defined(DEBUG) && 0
502 72899afc bellard
    printf("usb_hub: pid=0x%x\n", pid);
503 72899afc bellard
#endif
504 72899afc bellard
    if (dev->state == USB_STATE_DEFAULT &&
505 72899afc bellard
        dev->addr != 0 &&
506 4d611c9a pbrook
        p->devaddr != dev->addr &&
507 5fafdf24 ths
        (p->pid == USB_TOKEN_SETUP ||
508 5fafdf24 ths
         p->pid == USB_TOKEN_OUT ||
509 4d611c9a pbrook
         p->pid == USB_TOKEN_IN)) {
510 72899afc bellard
        /* broadcast the packet to the devices */
511 4d611c9a pbrook
        return usb_hub_broadcast_packet(s, p);
512 72899afc bellard
    }
513 4d611c9a pbrook
    return usb_generic_handle_packet(dev, p);
514 72899afc bellard
}
515 72899afc bellard
516 059809e4 bellard
static void usb_hub_handle_destroy(USBDevice *dev)
517 059809e4 bellard
{
518 059809e4 bellard
    USBHubState *s = (USBHubState *)dev;
519 a8e662b5 Gerd Hoffmann
    int i;
520 059809e4 bellard
521 a8e662b5 Gerd Hoffmann
    for (i = 0; i < s->nb_ports; i++) {
522 a8e662b5 Gerd Hoffmann
        usb_unregister_port(usb_bus_from_device(dev),
523 a8e662b5 Gerd Hoffmann
                            &s->ports[i].port);
524 a8e662b5 Gerd Hoffmann
    }
525 059809e4 bellard
}
526 059809e4 bellard
527 806b6024 Gerd Hoffmann
static int usb_hub_initfn(USBDevice *dev)
528 72899afc bellard
{
529 806b6024 Gerd Hoffmann
    USBHubState *s = DO_UPCAST(USBHubState, dev, dev);
530 72899afc bellard
    USBHubPort *port;
531 72899afc bellard
    int i;
532 72899afc bellard
533 806b6024 Gerd Hoffmann
    s->dev.speed  = USB_SPEED_FULL,
534 806b6024 Gerd Hoffmann
    s->nb_ports = MAX_PORTS; /* FIXME: make configurable */
535 806b6024 Gerd Hoffmann
    for (i = 0; i < s->nb_ports; i++) {
536 72899afc bellard
        port = &s->ports[i];
537 a5d2f727 Gerd Hoffmann
        usb_register_port(usb_bus_from_device(dev),
538 a5d2f727 Gerd Hoffmann
                          &port->port, s, i, usb_hub_attach);
539 72899afc bellard
        port->wPortStatus = PORT_STAT_POWER;
540 72899afc bellard
        port->wPortChange = 0;
541 72899afc bellard
    }
542 806b6024 Gerd Hoffmann
    return 0;
543 806b6024 Gerd Hoffmann
}
544 806b6024 Gerd Hoffmann
545 806b6024 Gerd Hoffmann
static struct USBDeviceInfo hub_info = {
546 06384698 Markus Armbruster
    .product_desc   = "QEMU USB Hub",
547 556cd098 Markus Armbruster
    .qdev.name      = "usb-hub",
548 806b6024 Gerd Hoffmann
    .qdev.size      = sizeof(USBHubState),
549 806b6024 Gerd Hoffmann
    .init           = usb_hub_initfn,
550 806b6024 Gerd Hoffmann
    .handle_packet  = usb_hub_handle_packet,
551 806b6024 Gerd Hoffmann
    .handle_reset   = usb_hub_handle_reset,
552 806b6024 Gerd Hoffmann
    .handle_control = usb_hub_handle_control,
553 806b6024 Gerd Hoffmann
    .handle_data    = usb_hub_handle_data,
554 806b6024 Gerd Hoffmann
    .handle_destroy = usb_hub_handle_destroy,
555 806b6024 Gerd Hoffmann
};
556 806b6024 Gerd Hoffmann
557 806b6024 Gerd Hoffmann
static void usb_hub_register_devices(void)
558 806b6024 Gerd Hoffmann
{
559 806b6024 Gerd Hoffmann
    usb_qdev_register(&hub_info);
560 72899afc bellard
}
561 806b6024 Gerd Hoffmann
device_init(usb_hub_register_devices)