|
|
1.1 root 1: /*
2: * QEMU USB HUB emulation
3: *
4: * Copyright (c) 2005 Fabrice Bellard
1.1.1.4 root 5: *
1.1 root 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: */
1.1.1.4 root 24: #include "qemu-common.h"
25: #include "usb.h"
1.1 root 26:
27: //#define DEBUG
28:
29: #define MAX_PORTS 8
30:
31: typedef struct USBHubPort {
32: USBPort port;
33: uint16_t wPortStatus;
34: uint16_t wPortChange;
35: } USBHubPort;
36:
37: typedef 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:
86: static 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 */
107: static 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; */
1.1.1.4 root 116: 0xc0, /* u8 bmAttributes;
1.1 root 117: Bit 7: must be set,
118: 6: Self-powered,
119: 5: Remote wakeup,
120: 4..0: resvd */
121: 0x00, /* u8 MaxPower; */
1.1.1.4 root 122:
1.1 root 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; */
1.1.1.4 root 144:
1.1 root 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:
154: static const uint8_t qemu_hub_hub_descriptor[] =
155: {
1.1.1.2 root 156: 0x00, /* u8 bLength; patched in later */
1.1 root 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:
167: static void usb_hub_attach(USBPort *port1, USBDevice *dev)
168: {
169: USBHubState *s = port1->opaque;
170: USBHubPort *port = &s->ports[port1->index];
1.1.1.4 root 171:
1.1 root 172: if (dev) {
173: if (port->port.dev)
174: usb_attach(port1, NULL);
1.1.1.4 root 175:
1.1 root 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;
1.1.1.2 root 183: /* send the attach message */
1.1.1.3 root 184: usb_send_msg(dev, USB_MSG_ATTACH);
1.1 root 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: }
1.1.1.2 root 194: /* send the detach message */
1.1.1.3 root 195: usb_send_msg(dev, USB_MSG_DETACH);
1.1 root 196: port->port.dev = NULL;
197: }
198: }
199: }
200:
201: static void usb_hub_handle_reset(USBDevice *dev)
202: {
203: /* XXX: do it */
204: }
205:
206: static 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:
1.1.1.4 root 248: memcpy(data, qemu_hub_dev_descriptor,
1.1 root 249: sizeof(qemu_hub_dev_descriptor));
250: ret = sizeof(qemu_hub_dev_descriptor);
251: break;
252: case USB_DT_CONFIG:
1.1.1.4 root 253: memcpy(data, qemu_hub_config_descriptor,
1.1 root 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) {
1.1.1.3 root 351: usb_send_msg(dev, USB_MSG_RESET);
1.1 root 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;
1.1.1.4 root 405: memcpy(data, qemu_hub_hub_descriptor,
1.1 root 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;
1.1.1.2 root 424: data[0] = ret;
1.1 root 425: break;
426: }
427: default:
428: fail:
429: ret = USB_RET_STALL;
430: break;
431: }
432: return ret;
433: }
434:
1.1.1.3 root 435: static int usb_hub_handle_data(USBDevice *dev, USBPacket *p)
1.1 root 436: {
437: USBHubState *s = (USBHubState *)dev;
438: int ret;
439:
1.1.1.3 root 440: switch(p->pid) {
1.1 root 441: case USB_TOKEN_IN:
1.1.1.3 root 442: if (p->devep == 1) {
1.1 root 443: USBHubPort *port;
444: unsigned int status;
445: int i, n;
446: n = (s->nb_ports + 1 + 7) / 8;
1.1.1.3 root 447: if (p->len == 1) { /* FreeBSD workaround */
1.1 root 448: n = 1;
1.1.1.3 root 449: } else if (n > p->len) {
1.1 root 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++) {
1.1.1.3 root 460: p->data[i] = status >> (8 * i);
1.1 root 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:
1.1.1.3 root 479: static int usb_hub_broadcast_packet(USBHubState *s, USBPacket *p)
1.1 root 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)) {
1.1.1.3 root 489: ret = dev->handle_packet(dev, p);
1.1 root 490: if (ret != USB_RET_NODEV) {
491: return ret;
492: }
493: }
494: }
495: return USB_RET_NODEV;
496: }
497:
1.1.1.3 root 498: static int usb_hub_handle_packet(USBDevice *dev, USBPacket *p)
1.1 root 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 &&
1.1.1.3 root 507: p->devaddr != dev->addr &&
1.1.1.4 root 508: (p->pid == USB_TOKEN_SETUP ||
509: p->pid == USB_TOKEN_OUT ||
1.1.1.3 root 510: p->pid == USB_TOKEN_IN)) {
1.1 root 511: /* broadcast the packet to the devices */
1.1.1.3 root 512: return usb_hub_broadcast_packet(s, p);
1.1 root 513: }
1.1.1.3 root 514: return usb_generic_handle_packet(dev, p);
1.1 root 515: }
516:
1.1.1.2 root 517: static void usb_hub_handle_destroy(USBDevice *dev)
518: {
519: USBHubState *s = (USBHubState *)dev;
520:
521: qemu_free(s);
522: }
523:
524: USBDevice *usb_hub_init(int nb_ports)
1.1 root 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;
1.1.1.2 root 540: s->dev.handle_destroy = usb_hub_handle_destroy;
541:
542: pstrcpy(s->dev.devname, sizeof(s->dev.devname), "QEMU USB Hub");
1.1 root 543:
544: s->nb_ports = nb_ports;
545: for(i = 0; i < s->nb_ports; i++) {
546: port = &s->ports[i];
1.1.1.2 root 547: qemu_register_usb_port(&port->port, s, i, usb_hub_attach);
1.1 root 548: port->wPortStatus = PORT_STAT_POWER;
549: port->wPortChange = 0;
550: }
551: return (USBDevice *)s;
552: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.