static int usb_hid_handle_control(USBDevice *dev, int request, int value, int index, int length, uint8_t *data) { USBHIDState *s = (USBHIDState *)dev; int ret = 0; switch(request) { case DeviceRequest | USB_REQ_GET_STATUS: data[0] = (1 << USB_DEVICE_SELF_POWERED) | (dev->remote_wakeup << USB_DEVICE_REMOTE_WAKEUP); data[1] = 0x00; ret = 2; break; case DeviceOutRequest | USB_REQ_CLEAR_FEATURE: if (value == USB_DEVICE_REMOTE_WAKEUP) { dev->remote_wakeup = 0; } else { goto fail; } ret = 0; break; case DeviceOutRequest | USB_REQ_SET_FEATURE: if (value == USB_DEVICE_REMOTE_WAKEUP) { dev->remote_wakeup = 1; } else { goto fail; } ret = 0; break; case DeviceOutRequest | USB_REQ_SET_ADDRESS: dev->addr = value; ret = 0; break; case DeviceRequest | USB_REQ_GET_DESCRIPTOR: switch(value >> 8) { case USB_DT_DEVICE: memcpy(data, qemu_mouse_dev_descriptor, sizeof(qemu_mouse_dev_descriptor)); ret = sizeof(qemu_mouse_dev_descriptor); break; case USB_DT_CONFIG: if (s->kind == USB_MOUSE) { memcpy(data, qemu_mouse_config_descriptor, sizeof(qemu_mouse_config_descriptor)); ret = sizeof(qemu_mouse_config_descriptor); } else if (s->kind == USB_TABLET) { memcpy(data, qemu_tablet_config_descriptor, sizeof(qemu_tablet_config_descriptor)); ret = sizeof(qemu_tablet_config_descriptor); } else if (s->kind == USB_KEYBOARD) { memcpy(data, qemu_keyboard_config_descriptor, sizeof(qemu_keyboard_config_descriptor)); ret = sizeof(qemu_keyboard_config_descriptor); } break; case USB_DT_STRING: switch(value & 0xff) { case 0: /* language ids */ data[0] = 4; data[1] = 3; data[2] = 0x09; data[3] = 0x04; ret = 4; break; case 1: /* serial number */ ret = set_usb_string(data, "1"); break; case 2: /* product description */ ret = set_usb_string(data, s->dev.devname); break; case 3: /* vendor description */ ret = set_usb_string(data, "QEMU " QEMU_VERSION); break; case 4: ret = set_usb_string(data, "HID Mouse"); break; case 5: ret = set_usb_string(data, "HID Tablet"); break; case 6: ret = set_usb_string(data, "HID Keyboard"); break; case 7: ret = set_usb_string(data, "Endpoint1 Interrupt Pipe"); 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; /* hid specific requests */ case InterfaceRequest | USB_REQ_GET_DESCRIPTOR: switch(value >> 8) { case 0x22: if (s->kind == USB_MOUSE) { memcpy(data, qemu_mouse_hid_report_descriptor, sizeof(qemu_mouse_hid_report_descriptor)); ret = sizeof(qemu_mouse_hid_report_descriptor); } else if (s->kind == USB_TABLET) { memcpy(data, qemu_tablet_hid_report_descriptor, sizeof(qemu_tablet_hid_report_descriptor)); ret = sizeof(qemu_tablet_hid_report_descriptor); } else if (s->kind == USB_KEYBOARD) { memcpy(data, qemu_keyboard_hid_report_descriptor, sizeof(qemu_keyboard_hid_report_descriptor)); ret = sizeof(qemu_keyboard_hid_report_descriptor); } break; default: goto fail; } break; case GET_REPORT: if (s->kind == USB_MOUSE) ret = usb_mouse_poll(s, data, length); else if (s->kind == USB_TABLET) ret = usb_tablet_poll(s, data, length); else if (s->kind == USB_KEYBOARD) ret = usb_keyboard_poll(&s->kbd, data, length); break; case SET_REPORT: if (s->kind == USB_KEYBOARD) ret = usb_keyboard_write(&s->kbd, data, length); else goto fail; break; case GET_PROTOCOL: if (s->kind != USB_KEYBOARD) goto fail; ret = 1; data[0] = s->protocol; break; case SET_PROTOCOL: if (s->kind != USB_KEYBOARD) goto fail; ret = 0; s->protocol = value; break; case GET_IDLE: ret = 1; data[0] = s->idle; break; case SET_IDLE: s->idle = value; ret = 0; break; default: fail: ret = USB_RET_STALL; break; } return ret; }
static int usb_hub_handle_control(USBDevice *dev, int request, int value, int index, int length, uint8_t *data) { USBHubState *s = (USBHubState *)dev; int ret; switch(request) { case DeviceRequest | USB_REQ_GET_STATUS: data[0] = (1 << USB_DEVICE_SELF_POWERED) | (dev->remote_wakeup << USB_DEVICE_REMOTE_WAKEUP); data[1] = 0x00; ret = 2; break; case DeviceOutRequest | USB_REQ_CLEAR_FEATURE: if (value == USB_DEVICE_REMOTE_WAKEUP) { dev->remote_wakeup = 0; } else { goto fail; } ret = 0; break; case EndpointOutRequest | USB_REQ_CLEAR_FEATURE: if (value == 0 && index != 0x81) { /* clear ep halt */ goto fail; } ret = 0; break; case DeviceOutRequest | USB_REQ_SET_FEATURE: if (value == USB_DEVICE_REMOTE_WAKEUP) { dev->remote_wakeup = 1; } else { goto fail; } ret = 0; break; case DeviceOutRequest | USB_REQ_SET_ADDRESS: dev->addr = value; ret = 0; break; case DeviceRequest | USB_REQ_GET_DESCRIPTOR: switch(value >> 8) { case USB_DT_DEVICE: memcpy(data, qemu_hub_dev_descriptor, sizeof(qemu_hub_dev_descriptor)); ret = sizeof(qemu_hub_dev_descriptor); break; case USB_DT_CONFIG: memcpy(data, qemu_hub_config_descriptor, sizeof(qemu_hub_config_descriptor)); /* status change endpoint size based on number * of ports */ data[22] = (s->nb_ports + 1 + 7) / 8; ret = sizeof(qemu_hub_config_descriptor); break; case USB_DT_STRING: switch(value & 0xff) { case 0: /* language ids */ data[0] = 4; data[1] = 3; data[2] = 0x09; data[3] = 0x04; ret = 4; break; case 1: /* serial number */ ret = set_usb_string(data, "314159"); break; case 2: /* product description */ ret = set_usb_string(data, "QEMU USB Hub"); 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_msd_handle_control(USBDevice *dev, int request, int value, int index, int length, uint8_t *data) { MSDState *s = (MSDState *)dev; int ret = 0; switch (request) { case DeviceRequest | USB_REQ_GET_STATUS: data[0] = (1 << USB_DEVICE_SELF_POWERED) | (dev->remote_wakeup << USB_DEVICE_REMOTE_WAKEUP); data[1] = 0x00; ret = 2; break; case DeviceOutRequest | USB_REQ_CLEAR_FEATURE: if (value == USB_DEVICE_REMOTE_WAKEUP) { dev->remote_wakeup = 0; } else { goto fail; } ret = 0; break; case DeviceOutRequest | USB_REQ_SET_FEATURE: if (value == USB_DEVICE_REMOTE_WAKEUP) { dev->remote_wakeup = 1; } else { goto fail; } ret = 0; break; case DeviceOutRequest | USB_REQ_SET_ADDRESS: dev->addr = value; ret = 0; break; case DeviceRequest | USB_REQ_GET_DESCRIPTOR: switch(value >> 8) { case USB_DT_DEVICE: memcpy(data, qemu_msd_dev_descriptor, sizeof(qemu_msd_dev_descriptor)); ret = sizeof(qemu_msd_dev_descriptor); break; case USB_DT_CONFIG: memcpy(data, qemu_msd_config_descriptor, sizeof(qemu_msd_config_descriptor)); ret = sizeof(qemu_msd_config_descriptor); break; case USB_DT_STRING: switch(value & 0xff) { case 0: /* language ids */ data[0] = 4; data[1] = 3; data[2] = 0x09; data[3] = 0x04; ret = 4; break; case 1: /* vendor description */ ret = set_usb_string(data, "QEMU " QEMU_VERSION); break; case 2: /* product description */ ret = set_usb_string(data, "QEMU USB HARDDRIVE"); break; case 3: /* serial number */ ret = set_usb_string(data, "1"); 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; case EndpointOutRequest | USB_REQ_CLEAR_FEATURE: if (value == 0 && index != 0x81) { /* clear ep halt */ goto fail; } ret = 0; break; /* Class specific requests. */ case MassStorageReset: /* Reset state ready for the next CBW. */ s->mode = USB_MSDM_CBW; ret = 0; break; case GetMaxLun: data[0] = 0; ret = 1; break; default: fail: ret = USB_RET_STALL; break; } return ret; }
static int singstar_mic_handle_control(USBDevice *dev, int request, int value, int index, int length, uint8_t *data) { SINGSTARMICState *s = (SINGSTARMICState *)dev; int ret = 0; switch(request) { case DeviceRequest | USB_REQ_GET_STATUS: data[0] = (dev->remote_wakeup << USB_DEVICE_REMOTE_WAKEUP); data[1] = 0x00; ret = 2; break; case DeviceOutRequest | USB_REQ_CLEAR_FEATURE: if (value == USB_DEVICE_REMOTE_WAKEUP) { dev->remote_wakeup = 0; } else { goto fail; } ret = 0; break; case DeviceOutRequest | USB_REQ_SET_FEATURE: if (value == USB_DEVICE_REMOTE_WAKEUP) { dev->remote_wakeup = 1; } else { goto fail; } ret = 0; break; case DeviceOutRequest | USB_REQ_SET_ADDRESS: dev->addr = value; ret = 0; break; case DeviceRequest | USB_REQ_GET_DESCRIPTOR: switch(value >> 8) { case USB_DT_DEVICE: memcpy(data, singstar_mic_dev_descriptor, sizeof(singstar_mic_dev_descriptor)); ret = sizeof(singstar_mic_dev_descriptor); break; case USB_DT_CONFIG: memcpy(data, singstar_mic_config_descriptor, sizeof(singstar_mic_config_descriptor)); ret = sizeof(singstar_mic_config_descriptor); break; case USB_DT_STRING: switch(value & 0xff) { case 0: /* language ids */ data[0] = 4; data[1] = 3; data[2] = 0x09; data[3] = 0x04; ret = 4; break; case 1: /* serial number */ ret = set_usb_string(data, "3X0420811"); break; case 2: /* product description */ ret = set_usb_string(data, "EyeToy USB camera Namtai"); break; case 3: /* vendor description */ ret = set_usb_string(data, "PCSX2/QEMU"); 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; /* hid specific requests */ case InterfaceRequest | USB_REQ_GET_DESCRIPTOR: //switch(value >> 8) { //((case 0x22: // memcpy(data, qemu_mouse_hid_report_descriptor, // sizeof(qemu_mouse_hid_report_descriptor)); // ret = sizeof(qemu_mouse_hid_report_descriptor); // break; //default: goto fail; //} break; case GET_REPORT: ret = 0; break; case SET_IDLE: ret = 0; break; default: fail: ret = USB_RET_STALL; break; } return ret; }
int usb_msd_device_t::handle_control(int request, int value, int index, int length, Bit8u *data) { int ret = 0; switch (request) { case DeviceRequest | USB_REQ_GET_STATUS: data[0] = (1 << USB_DEVICE_SELF_POWERED) | (d.remote_wakeup << USB_DEVICE_REMOTE_WAKEUP); data[1] = 0x00; ret = 2; break; case DeviceOutRequest | USB_REQ_CLEAR_FEATURE: if (value == USB_DEVICE_REMOTE_WAKEUP) { d.remote_wakeup = 0; } else { goto fail; } ret = 0; break; case DeviceOutRequest | USB_REQ_SET_FEATURE: if (value == USB_DEVICE_REMOTE_WAKEUP) { d.remote_wakeup = 1; } else { goto fail; } ret = 0; break; case DeviceOutRequest | USB_REQ_SET_ADDRESS: d.addr = value; ret = 0; break; case DeviceRequest | USB_REQ_GET_DESCRIPTOR: switch(value >> 8) { case USB_DT_DEVICE: memcpy(data, bx_msd_dev_descriptor, sizeof(bx_msd_dev_descriptor)); ret = sizeof(bx_msd_dev_descriptor); break; case USB_DT_CONFIG: memcpy(data, bx_msd_config_descriptor, sizeof(bx_msd_config_descriptor)); ret = sizeof(bx_msd_config_descriptor); break; case USB_DT_STRING: switch(value & 0xff) { case 0: // language IDs data[0] = 4; data[1] = 3; data[2] = 0x09; data[3] = 0x04; ret = 4; break; case 1: // vendor description ret = set_usb_string(data, "BOCHS"); break; case 2: // product description if (strlen(d.devname) > 0) { ret = set_usb_string(data, d.devname); } else { goto fail; } break; case 3: // serial number ret = set_usb_string(data, "1"); break; default: BX_ERROR(("USB MSD handle_control: unknown descriptor 0x%02x", value & 0xff)); goto fail; } break; case USB_DT_DEVICE_QUALIFIER: // device qualifier data[0] = 10; data[1] = USB_DT_DEVICE_QUALIFIER; memcpy(data+2, bx_msd_dev_descriptor+2, 6); data[8] = 1; data[9] = 0; ret = 10; 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; case EndpointOutRequest | USB_REQ_CLEAR_FEATURE: if (value == 0 && index != 0x81) { /* clear ep halt */ goto fail; } ret = 0; break; // Class specific requests case MassStorageReset: // Ben: Hack for 0x21 | MassStorageReset // 0x21 = (REQ_TYPE_CLASS | RECPT_INTERFACE); case 0x21FF: s.mode = USB_MSDM_CBW; ret = 0; break; case GetMaxLun: data[0] = 0; ret = 1; break; default: BX_ERROR(("USB MSD handle_control: unknown request 0x%04x", request)); fail: ret = USB_RET_STALL; break; } return ret; }
static int usb_keyboard_handle_control(USBDevice *dev, int request, int value, int index, int length, uint8_t *data) { USBKeyboardState *s = (USBKeyboardState *)dev; int ret = 0; unsigned char buf[8]; switch(request) { case DeviceRequest | USB_REQ_GET_STATUS: data[0] = (1 << USB_DEVICE_SELF_POWERED) | (dev->remote_wakeup << USB_DEVICE_REMOTE_WAKEUP); data[1] = 0x00; ret = 2; break; case DeviceOutRequest | USB_REQ_CLEAR_FEATURE: if (value == USB_DEVICE_REMOTE_WAKEUP) { dev->remote_wakeup = 0; } else { goto fail; } ret = 0; break; case DeviceOutRequest | USB_REQ_SET_FEATURE: if (value == USB_DEVICE_REMOTE_WAKEUP) { dev->remote_wakeup = 1; } else { goto fail; } ret = 0; break; case DeviceOutRequest | USB_REQ_SET_ADDRESS: dev->addr = value; ret = 0; break; case DeviceRequest | USB_REQ_GET_DESCRIPTOR: switch(value >> 8) { case USB_DT_DEVICE: memcpy(data, qemu_keyboard_dev_descriptor, sizeof(qemu_keyboard_dev_descriptor)); ret = sizeof(qemu_keyboard_dev_descriptor); break; case USB_DT_CONFIG: memcpy(data, qemu_keyboard_config_descriptor, sizeof(qemu_keyboard_config_descriptor)); ret = sizeof(qemu_keyboard_config_descriptor); break; case USB_DT_STRING: switch(value & 0xff) { case 0: /* language ids */ data[0] = 4; data[1] = 3; data[2] = 0x09; data[3] = 0x04; ret = 4; break; case 1: /* serial number */ ret = set_usb_string(data, "1"); break; case 2: /* product description */ ret = set_usb_string(data, "Generic USB Keyboard"); break; case 3: /* vendor description */ ret = set_usb_string(data, "PCSX2/QEMU"); break; case 4: ret = set_usb_string(data, "HID Keyboard"); break; case 5: ret = set_usb_string(data, "Endpoint1 Interrupt Pipe"); 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; /* hid specific requests */ case InterfaceRequest | USB_REQ_GET_DESCRIPTOR: switch(value >> 8) { case 0x22: memcpy(data, qemu_keyboard_hid_report_descriptor, sizeof(qemu_keyboard_hid_report_descriptor)); ret = sizeof(qemu_keyboard_hid_report_descriptor); break; default: goto fail; } break; case GET_REPORT: ret = usb_keyboard_poll(s, data, length); break; case 0x2109: ret=0; memset(buf, 0, 8); buf[2]=data[1]; buf[3]=data[2]; buf[4]=data[3]; buf[5]=data[4]; // printf("Lamps %02X %02X %02X %02X %02X %02X %02X\nlen = %i\n", data[0], data[1], data[2], data[3], data[4], data[5], data[6], length); CancelIo(usb_buzzer); WriteFile(usb_buzzer, buf, 8, 0, &ovl); break; case SET_IDLE: ret = 0; break; default: printf("Bad request value %08X", request); fail: ret = USB_RET_STALL; break; } return ret; }