?? usb-hid.c
字號:
case 0xe8 ... 0xef: s->modifiers |= 1 << (hid_code & 0x0f); return; } if (keycode & (1 << 7)) { for (i = s->keys - 1; i >= 0; i --) if (s->key[i] == hid_code) { s->key[i] = s->key[-- s->keys]; s->key[s->keys] = 0x00; return; } } else { for (i = s->keys - 1; i >= 0; i --) if (s->key[i] == hid_code) return; if (s->keys < sizeof(s->key)) s->key[s->keys ++] = hid_code; }}static inline int int_clamp(int val, int vmin, int vmax){ if (val < vmin) return vmin; else if (val > vmax) return vmax; else return val;}static int usb_mouse_poll(USBHIDState *hs, uint8_t *buf, int len){ int dx, dy, dz, b, l; USBMouseState *s = &hs->ptr; if (!s->mouse_grabbed) { s->eh_entry = qemu_add_mouse_event_handler(usb_mouse_event, hs, 0, "QEMU USB Mouse"); s->mouse_grabbed = 1; } dx = int_clamp(s->dx, -128, 127); dy = int_clamp(s->dy, -128, 127); dz = int_clamp(s->dz, -128, 127); s->dx -= dx; s->dy -= dy; s->dz -= dz; b = 0; if (s->buttons_state & MOUSE_EVENT_LBUTTON) b |= 0x01; if (s->buttons_state & MOUSE_EVENT_RBUTTON) b |= 0x02; if (s->buttons_state & MOUSE_EVENT_MBUTTON) b |= 0x04; buf[0] = b; buf[1] = dx; buf[2] = dy; l = 3; if (len >= 4) { buf[3] = dz; l = 4; } return l;}static int usb_tablet_poll(USBHIDState *hs, uint8_t *buf, int len){ int dz, b, l; USBMouseState *s = &hs->ptr; if (!s->mouse_grabbed) { s->eh_entry = qemu_add_mouse_event_handler(usb_tablet_event, hs, 1, "QEMU USB Tablet"); s->mouse_grabbed = 1; } dz = int_clamp(s->dz, -128, 127); s->dz -= dz; /* Appears we have to invert the wheel direction */ dz = 0 - dz; b = 0; if (s->buttons_state & MOUSE_EVENT_LBUTTON) b |= 0x01; if (s->buttons_state & MOUSE_EVENT_RBUTTON) b |= 0x02; if (s->buttons_state & MOUSE_EVENT_MBUTTON) b |= 0x04; buf[0] = b; buf[1] = s->x & 0xff; buf[2] = s->x >> 8; buf[3] = s->y & 0xff; buf[4] = s->y >> 8; buf[5] = dz; l = 6; return l;}static int usb_keyboard_poll(USBKeyboardState *s, uint8_t *buf, int len){ if (len < 2) return 0; buf[0] = s->modifiers & 0xff; buf[1] = 0; if (s->keys > 6) memset(buf + 2, USB_HID_USAGE_ERROR_ROLLOVER, MIN(8, len) - 2); else memcpy(buf + 2, s->key, MIN(8, len) - 2); return MIN(8, len);}static int usb_keyboard_write(USBKeyboardState *s, uint8_t *buf, int len){ if (len > 0) { /* 0x01: Num Lock LED * 0x02: Caps Lock LED * 0x04: Scroll Lock LED * 0x08: Compose LED * 0x10: Kana LED */ s->leds = buf[0]; } return 0;}static void usb_mouse_handle_reset(USBDevice *dev){ USBHIDState *s = (USBHIDState *)dev; s->ptr.dx = 0; s->ptr.dy = 0; s->ptr.dz = 0; s->ptr.x = 0; s->ptr.y = 0; s->ptr.buttons_state = 0; s->protocol = 1;}static void usb_keyboard_handle_reset(USBDevice *dev){ USBHIDState *s = (USBHIDState *)dev; qemu_add_kbd_event_handler(usb_keyboard_event, s); s->protocol = 1;}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_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 void usb_hid_handle_destroy(USBDevice *dev){ USBHIDState *s = (USBHIDState *)dev; if (s->kind != USB_KEYBOARD) qemu_remove_mouse_event_handler(s->ptr.eh_entry); /* TODO: else */ qemu_free(s);}USBDevice *usb_tablet_init(void){ USBHIDState *s; s = qemu_mallocz(sizeof(USBHIDState)); if (!s) return NULL; s->dev.speed = USB_SPEED_FULL; s->dev.handle_packet = usb_generic_handle_packet; s->dev.handle_reset = usb_mouse_handle_reset; s->dev.handle_control = usb_hid_handle_control; s->dev.handle_data = usb_hid_handle_data; s->dev.handle_destroy = usb_hid_handle_destroy; s->kind = USB_TABLET; /* Force poll routine to be run and grab input the first time. */ s->changed = 1; pstrcpy(s->dev.devname, sizeof(s->dev.devname), "QEMU USB Tablet"); return (USBDevice *)s;}USBDevice *usb_mouse_init(void){ USBHIDState *s; s = qemu_mallocz(sizeof(USBHIDState)); if (!s) return NULL; s->dev.speed = USB_SPEED_FULL; s->dev.handle_packet = usb_generic_handle_packet; s->dev.handle_reset = usb_mouse_handle_reset; s->dev.handle_control = usb_hid_handle_control; s->dev.handle_data = usb_hid_handle_data; s->dev.handle_destroy = usb_hid_handle_destroy; s->kind = USB_MOUSE; /* Force poll routine to be run and grab input the first time. */ s->changed = 1; pstrcpy(s->dev.devname, sizeof(s->dev.devname), "QEMU USB Mouse"); return (USBDevice *)s;}USBDevice *usb_keyboard_init(void){ USBHIDState *s; s = qemu_mallocz(sizeof(USBHIDState)); if (!s) return NULL; s->dev.speed = USB_SPEED_FULL; s->dev.handle_packet = usb_generic_handle_packet; s->dev.handle_reset = usb_keyboard_handle_reset; s->dev.handle_control = usb_hid_handle_control; s->dev.handle_data = usb_hid_handle_data; s->dev.handle_destroy = usb_hid_handle_destroy; s->kind = USB_KEYBOARD; pstrcpy(s->dev.devname, sizeof(s->dev.devname), "QEMU USB Keyboard"); return (USBDevice *) s;}
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -