📄 usb-hub.c.svn-base
字号:
break; case 3: /* vendor description */ ret = set_usb_string(data, "QEMU " QEMU_VERSION); break; default: goto fail; } break; default: goto fail; } break; case DeviceRequest | USB_REQ_GET_CONFIGURATION: data[0] = 1; ret = 1; break; case DeviceOutRequest | USB_REQ_SET_CONFIGURATION: ret = 0; break; case DeviceRequest | USB_REQ_GET_INTERFACE: data[0] = 0; ret = 1; break; case DeviceOutRequest | USB_REQ_SET_INTERFACE: ret = 0; break; /* usb specific requests */ case GetHubStatus: data[0] = 0; data[1] = 0; data[2] = 0; data[3] = 0; ret = 4; break; case GetPortStatus: { unsigned int n = index - 1; USBHubPort *port; if (n >= s->nb_ports) goto fail; port = &s->ports[n]; data[0] = port->wPortStatus; data[1] = port->wPortStatus >> 8; data[2] = port->wPortChange; data[3] = port->wPortChange >> 8; ret = 4; } break; case SetHubFeature: case ClearHubFeature: if (value == 0 || value == 1) { } else { goto fail; } ret = 0; break; case SetPortFeature: { unsigned int n = index - 1; USBHubPort *port; USBDevice *dev; if (n >= s->nb_ports) goto fail; port = &s->ports[n]; dev = port->port.dev; switch(value) { case PORT_SUSPEND: port->wPortStatus |= PORT_STAT_SUSPEND; break; case PORT_RESET: if (dev) { usb_send_msg(dev, USB_MSG_RESET); port->wPortChange |= PORT_STAT_C_RESET; /* set enable bit */ port->wPortStatus |= PORT_STAT_ENABLE; } break; case PORT_POWER: break; default: goto fail; } ret = 0; } break; case ClearPortFeature: { unsigned int n = index - 1; USBHubPort *port; USBDevice *dev; if (n >= s->nb_ports) goto fail; port = &s->ports[n]; dev = port->port.dev; switch(value) { case PORT_ENABLE: port->wPortStatus &= ~PORT_STAT_ENABLE; break; case PORT_C_ENABLE: port->wPortChange &= ~PORT_STAT_C_ENABLE; break; case PORT_SUSPEND: port->wPortStatus &= ~PORT_STAT_SUSPEND; break; case PORT_C_SUSPEND: port->wPortChange &= ~PORT_STAT_C_SUSPEND; break; case PORT_C_CONNECTION: port->wPortChange &= ~PORT_STAT_C_CONNECTION; break; case PORT_C_OVERCURRENT: port->wPortChange &= ~PORT_STAT_C_OVERCURRENT; break; case PORT_C_RESET: port->wPortChange &= ~PORT_STAT_C_RESET; break; default: goto fail; } ret = 0; } break; case GetHubDescriptor: { unsigned int n, limit, var_hub_size = 0; memcpy(data, qemu_hub_hub_descriptor, sizeof(qemu_hub_hub_descriptor)); data[2] = s->nb_ports; /* fill DeviceRemovable bits */ limit = ((s->nb_ports + 1 + 7) / 8) + 7; for (n = 7; n < limit; n++) { data[n] = 0x00; var_hub_size++; } /* fill PortPwrCtrlMask bits */ limit = limit + ((s->nb_ports + 7) / 8); for (;n < limit; n++) { data[n] = 0xff; var_hub_size++; } ret = sizeof(qemu_hub_hub_descriptor) + var_hub_size; data[0] = ret; break; } default: fail: ret = USB_RET_STALL; break; } return ret;}static int usb_hub_handle_data(USBDevice *dev, USBPacket *p){ USBHubState *s = (USBHubState *)dev; int ret; switch(p->pid) { case USB_TOKEN_IN: if (p->devep == 1) { USBHubPort *port; unsigned int status; int i, n; n = (s->nb_ports + 1 + 7) / 8; if (p->len == 1) { /* FreeBSD workaround */ n = 1; } else if (n > p->len) { return USB_RET_BABBLE; } status = 0; for(i = 0; i < s->nb_ports; i++) { port = &s->ports[i]; if (port->wPortChange) status |= (1 << (i + 1)); } if (status != 0) { for(i = 0; i < n; i++) { p->data[i] = status >> (8 * i); } ret = n; } else { ret = USB_RET_NAK; /* usb11 11.13.1 */ } } else { goto fail; } break; case USB_TOKEN_OUT: default: fail: ret = USB_RET_STALL; break; } return ret;}static int usb_hub_broadcast_packet(USBHubState *s, USBPacket *p){ USBHubPort *port; USBDevice *dev; int i, ret; for(i = 0; i < s->nb_ports; i++) { port = &s->ports[i]; dev = port->port.dev; if (dev && (port->wPortStatus & PORT_STAT_ENABLE)) { ret = dev->handle_packet(dev, p); if (ret != USB_RET_NODEV) { return ret; } } } return USB_RET_NODEV;}static int usb_hub_handle_packet(USBDevice *dev, USBPacket *p){ USBHubState *s = (USBHubState *)dev;#if defined(DEBUG) && 0 printf("usb_hub: pid=0x%x\n", pid);#endif if (dev->state == USB_STATE_DEFAULT && dev->addr != 0 && p->devaddr != dev->addr && (p->pid == USB_TOKEN_SETUP || p->pid == USB_TOKEN_OUT || p->pid == USB_TOKEN_IN)) { /* broadcast the packet to the devices */ return usb_hub_broadcast_packet(s, p); } return usb_generic_handle_packet(dev, p);}static void usb_hub_handle_destroy(USBDevice *dev){ USBHubState *s = (USBHubState *)dev; qemu_free(s);}USBDevice *usb_hub_init(int nb_ports){ USBHubState *s; USBHubPort *port; int i; if (nb_ports > MAX_PORTS) return NULL; s = qemu_mallocz(sizeof(USBHubState)); if (!s) return NULL; s->dev.speed = USB_SPEED_FULL; s->dev.handle_packet = usb_hub_handle_packet; /* generic USB device init */ s->dev.handle_reset = usb_hub_handle_reset; s->dev.handle_control = usb_hub_handle_control; s->dev.handle_data = usb_hub_handle_data; s->dev.handle_destroy = usb_hub_handle_destroy; pstrcpy(s->dev.devname, sizeof(s->dev.devname), "QEMU USB Hub"); s->nb_ports = nb_ports; for(i = 0; i < s->nb_ports; i++) { port = &s->ports[i]; qemu_register_usb_port(&port->port, s, i, usb_hub_attach); port->wPortStatus = PORT_STAT_POWER; port->wPortChange = 0; } return (USBDevice *)s;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -