Statistics
| Branch: | Revision:

root / hw / usb-hub.c @ 0986ac3b

History | View | Annotate | Download (16.7 kB)

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