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