static int usb_hid_handle_data(USBDevice *dev, USBPacket *p) { USBHIDState *s = (USBHIDState *)dev; int ret = 0; switch(p->pid) { case USB_TOKEN_IN: if (p->devep == 1) { /* TODO: Implement finite idle delays. */ if (!(s->changed || s->idle)) return USB_RET_NAK; s->changed = 0; if (s->kind == USB_MOUSE) ret = usb_mouse_poll(s, p->data, p->len); else if (s->kind == USB_TABLET) ret = usb_tablet_poll(s, p->data, p->len); else if (s->kind == USB_KEYBOARD) ret = usb_keyboard_poll(&s->kbd, p->data, p->len); } else { goto fail; } break; case USB_TOKEN_OUT: default: fail: ret = USB_RET_STALL; break; } return ret; }
static int usb_mouse_handle_data(USBDevice *dev, int pid, uint8_t devep, uint8_t *data, int len) { USBMouseState *s = (USBMouseState *)dev; int ret = 0; switch(pid) { case USB_TOKEN_IN: if (devep == 1) { if (s->kind == USB_MOUSE) ret = usb_mouse_poll(s, data, len); else if (s->kind == USB_TABLET) ret = usb_tablet_poll(s, data, len); } else { goto fail; } break; case USB_TOKEN_OUT: default: fail: ret = USB_RET_STALL; break; } return ret; }
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; }