?? usb-hid.c
字號:
/* * QEMU USB HID devices * * Copyright (c) 2005 Fabrice Bellard * Copyright (c) 2007 OpenMoko, Inc. (andrew@openedhand.com) * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */#include "hw.h"#include "console.h"#include "usb.h"/* HID interface requests */#define GET_REPORT 0xa101#define GET_IDLE 0xa102#define GET_PROTOCOL 0xa103#define SET_REPORT 0x2109#define SET_IDLE 0x210a#define SET_PROTOCOL 0x210b/* HID descriptor types */#define USB_DT_HID 0x21#define USB_DT_REPORT 0x22#define USB_DT_PHY 0x23#define USB_MOUSE 1#define USB_TABLET 2#define USB_KEYBOARD 3typedef struct USBMouseState { int dx, dy, dz, buttons_state; int x, y; int mouse_grabbed; QEMUPutMouseEntry *eh_entry;} USBMouseState;typedef struct USBKeyboardState { uint16_t modifiers; uint8_t leds; uint8_t key[16]; int keys;} USBKeyboardState;typedef struct USBHIDState { USBDevice dev; union { USBMouseState ptr; USBKeyboardState kbd; }; int kind; int protocol; int idle; int changed;} USBHIDState;/* mostly the same values as the Bochs USB Mouse device */static const uint8_t qemu_mouse_dev_descriptor[] = { 0x12, /* u8 bLength; */ 0x01, /* u8 bDescriptorType; Device */ 0x00, 0x01, /* u16 bcdUSB; v1.0 */ 0x00, /* u8 bDeviceClass; */ 0x00, /* u8 bDeviceSubClass; */ 0x00, /* u8 bDeviceProtocol; [ low/full speeds only ] */ 0x08, /* u8 bMaxPacketSize0; 8 Bytes */ 0x27, 0x06, /* u16 idVendor; */ 0x01, 0x00, /* u16 idProduct; */ 0x00, 0x00, /* u16 bcdDevice */ 0x03, /* u8 iManufacturer; */ 0x02, /* u8 iProduct; */ 0x01, /* u8 iSerialNumber; */ 0x01 /* u8 bNumConfigurations; */};static const uint8_t qemu_mouse_config_descriptor[] = { /* one configuration */ 0x09, /* u8 bLength; */ 0x02, /* u8 bDescriptorType; Configuration */ 0x22, 0x00, /* u16 wTotalLength; */ 0x01, /* u8 bNumInterfaces; (1) */ 0x01, /* u8 bConfigurationValue; */ 0x04, /* u8 iConfiguration; */ 0xa0, /* u8 bmAttributes; Bit 7: must be set, 6: Self-powered, 5: Remote wakeup, 4..0: resvd */ 50, /* u8 MaxPower; */ /* USB 1.1: * USB 2.0, single TT organization (mandatory): * one interface, protocol 0 * * USB 2.0, multiple TT organization (optional): * two interfaces, protocols 1 (like single TT) * and 2 (multiple TT mode) ... config is * sometimes settable * NOT IMPLEMENTED */ /* one interface */ 0x09, /* u8 if_bLength; */ 0x04, /* u8 if_bDescriptorType; Interface */ 0x00, /* u8 if_bInterfaceNumber; */ 0x00, /* u8 if_bAlternateSetting; */ 0x01, /* u8 if_bNumEndpoints; */ 0x03, /* u8 if_bInterfaceClass; */ 0x01, /* u8 if_bInterfaceSubClass; */ 0x02, /* u8 if_bInterfaceProtocol; [usb1.1 or single tt] */ 0x07, /* u8 if_iInterface; */ /* HID descriptor */ 0x09, /* u8 bLength; */ 0x21, /* u8 bDescriptorType; */ 0x01, 0x00, /* u16 HID_class */ 0x00, /* u8 country_code */ 0x01, /* u8 num_descriptors */ 0x22, /* u8 type; Report */ 50, 0, /* u16 len */ /* one endpoint (status change endpoint) */ 0x07, /* u8 ep_bLength; */ 0x05, /* u8 ep_bDescriptorType; Endpoint */ 0x81, /* u8 ep_bEndpointAddress; IN Endpoint 1 */ 0x03, /* u8 ep_bmAttributes; Interrupt */ 0x03, 0x00, /* u16 ep_wMaxPacketSize; */ 0x0a, /* u8 ep_bInterval; (255ms -- usb 2.0 spec) */};static const uint8_t qemu_tablet_config_descriptor[] = { /* one configuration */ 0x09, /* u8 bLength; */ 0x02, /* u8 bDescriptorType; Configuration */ 0x22, 0x00, /* u16 wTotalLength; */ 0x01, /* u8 bNumInterfaces; (1) */ 0x01, /* u8 bConfigurationValue; */ 0x05, /* u8 iConfiguration; */ 0xa0, /* u8 bmAttributes; Bit 7: must be set, 6: Self-powered, 5: Remote wakeup, 4..0: resvd */ 50, /* u8 MaxPower; */ /* USB 1.1: * USB 2.0, single TT organization (mandatory): * one interface, protocol 0 * * USB 2.0, multiple TT organization (optional): * two interfaces, protocols 1 (like single TT) * and 2 (multiple TT mode) ... config is * sometimes settable * NOT IMPLEMENTED */ /* one interface */ 0x09, /* u8 if_bLength; */ 0x04, /* u8 if_bDescriptorType; Interface */ 0x00, /* u8 if_bInterfaceNumber; */ 0x00, /* u8 if_bAlternateSetting; */ 0x01, /* u8 if_bNumEndpoints; */ 0x03, /* u8 if_bInterfaceClass; */ 0x01, /* u8 if_bInterfaceSubClass; */ 0x02, /* u8 if_bInterfaceProtocol; [usb1.1 or single tt] */ 0x07, /* u8 if_iInterface; */ /* HID descriptor */ 0x09, /* u8 bLength; */ 0x21, /* u8 bDescriptorType; */ 0x01, 0x00, /* u16 HID_class */ 0x00, /* u8 country_code */ 0x01, /* u8 num_descriptors */ 0x22, /* u8 type; Report */ 74, 0, /* u16 len */ /* one endpoint (status change endpoint) */ 0x07, /* u8 ep_bLength; */ 0x05, /* u8 ep_bDescriptorType; Endpoint */ 0x81, /* u8 ep_bEndpointAddress; IN Endpoint 1 */ 0x03, /* u8 ep_bmAttributes; Interrupt */ 0x08, 0x00, /* u16 ep_wMaxPacketSize; */ 0x0a, /* u8 ep_bInterval; (255ms -- usb 2.0 spec) */};static const uint8_t qemu_keyboard_config_descriptor[] = { /* one configuration */ 0x09, /* u8 bLength; */ USB_DT_CONFIG, /* u8 bDescriptorType; Configuration */ 0x22, 0x00, /* u16 wTotalLength; */ 0x01, /* u8 bNumInterfaces; (1) */ 0x01, /* u8 bConfigurationValue; */ 0x06, /* u8 iConfiguration; */ 0xa0, /* u8 bmAttributes; Bit 7: must be set, 6: Self-powered, 5: Remote wakeup, 4..0: resvd */ 0x32, /* u8 MaxPower; */ /* USB 1.1: * USB 2.0, single TT organization (mandatory): * one interface, protocol 0 * * USB 2.0, multiple TT organization (optional): * two interfaces, protocols 1 (like single TT) * and 2 (multiple TT mode) ... config is * sometimes settable * NOT IMPLEMENTED */ /* one interface */ 0x09, /* u8 if_bLength; */ USB_DT_INTERFACE, /* u8 if_bDescriptorType; Interface */ 0x00, /* u8 if_bInterfaceNumber; */ 0x00, /* u8 if_bAlternateSetting; */ 0x01, /* u8 if_bNumEndpoints; */ 0x03, /* u8 if_bInterfaceClass; HID */ 0x01, /* u8 if_bInterfaceSubClass; Boot */ 0x01, /* u8 if_bInterfaceProtocol; Keyboard */ 0x07, /* u8 if_iInterface; */ /* HID descriptor */ 0x09, /* u8 bLength; */ USB_DT_HID, /* u8 bDescriptorType; */ 0x11, 0x01, /* u16 HID_class */ 0x00, /* u8 country_code */ 0x01, /* u8 num_descriptors */ USB_DT_REPORT, /* u8 type; Report */ 0x3f, 0x00, /* u16 len */ /* one endpoint (status change endpoint) */ 0x07, /* u8 ep_bLength; */ USB_DT_ENDPOINT, /* u8 ep_bDescriptorType; Endpoint */ USB_DIR_IN | 0x01, /* u8 ep_bEndpointAddress; IN Endpoint 1 */ 0x03, /* u8 ep_bmAttributes; Interrupt */ 0x08, 0x00, /* u16 ep_wMaxPacketSize; */ 0x0a, /* u8 ep_bInterval; (255ms -- usb 2.0 spec) */};static const uint8_t qemu_mouse_hid_report_descriptor[] = { 0x05, 0x01, 0x09, 0x02, 0xA1, 0x01, 0x09, 0x01, 0xA1, 0x00, 0x05, 0x09, 0x19, 0x01, 0x29, 0x03, 0x15, 0x00, 0x25, 0x01, 0x95, 0x03, 0x75, 0x01, 0x81, 0x02, 0x95, 0x01, 0x75, 0x05, 0x81, 0x01, 0x05, 0x01, 0x09, 0x30, 0x09, 0x31, 0x15, 0x81, 0x25, 0x7F, 0x75, 0x08, 0x95, 0x02, 0x81, 0x06, 0xC0, 0xC0,};static const uint8_t qemu_tablet_hid_report_descriptor[] = { 0x05, 0x01, /* Usage Page Generic Desktop */ 0x09, 0x01, /* Usage Mouse */ 0xA1, 0x01, /* Collection Application */ 0x09, 0x01, /* Usage Pointer */ 0xA1, 0x00, /* Collection Physical */ 0x05, 0x09, /* Usage Page Button */ 0x19, 0x01, /* Usage Minimum Button 1 */ 0x29, 0x03, /* Usage Maximum Button 3 */ 0x15, 0x00, /* Logical Minimum 0 */ 0x25, 0x01, /* Logical Maximum 1 */ 0x95, 0x03, /* Report Count 3 */ 0x75, 0x01, /* Report Size 1 */ 0x81, 0x02, /* Input (Data, Var, Abs) */ 0x95, 0x01, /* Report Count 1 */ 0x75, 0x05, /* Report Size 5 */ 0x81, 0x01, /* Input (Cnst, Var, Abs) */ 0x05, 0x01, /* Usage Page Generic Desktop */ 0x09, 0x30, /* Usage X */ 0x09, 0x31, /* Usage Y */ 0x15, 0x00, /* Logical Minimum 0 */ 0x26, 0xFF, 0x7F, /* Logical Maximum 0x7fff */ 0x35, 0x00, /* Physical Minimum 0 */ 0x46, 0xFE, 0x7F, /* Physical Maximum 0x7fff */ 0x75, 0x10, /* Report Size 16 */ 0x95, 0x02, /* Report Count 2 */ 0x81, 0x02, /* Input (Data, Var, Abs) */ 0x05, 0x01, /* Usage Page Generic Desktop */ 0x09, 0x38, /* Usage Wheel */ 0x15, 0x81, /* Logical Minimum -127 */ 0x25, 0x7F, /* Logical Maximum 127 */ 0x35, 0x00, /* Physical Minimum 0 (same as logical) */ 0x45, 0x00, /* Physical Maximum 0 (same as logical) */ 0x75, 0x08, /* Report Size 8 */ 0x95, 0x01, /* Report Count 1 */ 0x81, 0x02, /* Input (Data, Var, Rel) */ 0xC0, /* End Collection */ 0xC0, /* End Collection */};static const uint8_t qemu_keyboard_hid_report_descriptor[] = { 0x05, 0x01, /* Usage Page (Generic Desktop) */ 0x09, 0x06, /* Usage (Keyboard) */ 0xa1, 0x01, /* Collection (Application) */ 0x75, 0x01, /* Report Size (1) */ 0x95, 0x08, /* Report Count (8) */ 0x05, 0x07, /* Usage Page (Key Codes) */ 0x19, 0xe0, /* Usage Minimum (224) */ 0x29, 0xe7, /* Usage Maximum (231) */ 0x15, 0x00, /* Logical Minimum (0) */ 0x25, 0x01, /* Logical Maximum (1) */ 0x81, 0x02, /* Input (Data, Variable, Absolute) */ 0x95, 0x01, /* Report Count (1) */ 0x75, 0x08, /* Report Size (8) */ 0x81, 0x01, /* Input (Constant) */ 0x95, 0x05, /* Report Count (5) */ 0x75, 0x01, /* Report Size (1) */ 0x05, 0x08, /* Usage Page (LEDs) */ 0x19, 0x01, /* Usage Minimum (1) */ 0x29, 0x05, /* Usage Maximum (5) */ 0x91, 0x02, /* Output (Data, Variable, Absolute) */ 0x95, 0x01, /* Report Count (1) */ 0x75, 0x03, /* Report Size (3) */ 0x91, 0x01, /* Output (Constant) */ 0x95, 0x06, /* Report Count (6) */ 0x75, 0x08, /* Report Size (8) */ 0x15, 0x00, /* Logical Minimum (0) */ 0x25, 0xff, /* Logical Maximum (255) */ 0x05, 0x07, /* Usage Page (Key Codes) */ 0x19, 0x00, /* Usage Minimum (0) */ 0x29, 0xff, /* Usage Maximum (255) */ 0x81, 0x00, /* Input (Data, Array) */ 0xc0, /* End Collection */};#define USB_HID_USAGE_ERROR_ROLLOVER 0x01#define USB_HID_USAGE_POSTFAIL 0x02#define USB_HID_USAGE_ERROR_UNDEFINED 0x03/* Indices are QEMU keycodes, values are from HID Usage Table. Indices * above 0x80 are for keys that come after 0xe0 or 0xe1+0x1d or 0xe1+0x9d. */static const uint8_t usb_hid_usage_keys[0x100] = { 0x00, 0x29, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x2d, 0x2e, 0x2a, 0x2b, 0x14, 0x1a, 0x08, 0x15, 0x17, 0x1c, 0x18, 0x0c, 0x12, 0x13, 0x2f, 0x30, 0x28, 0xe0, 0x04, 0x16, 0x07, 0x09, 0x0a, 0x0b, 0x0d, 0x0e, 0x0f, 0x33, 0x34, 0x35, 0xe1, 0x31, 0x1d, 0x1b, 0x06, 0x19, 0x05, 0x11, 0x10, 0x36, 0x37, 0x38, 0xe5, 0x55, 0xe2, 0x2c, 0x32, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, 0x40, 0x41, 0x42, 0x43, 0x53, 0x47, 0x5f, 0x60, 0x61, 0x56, 0x5c, 0x5d, 0x5e, 0x57, 0x59, 0x5a, 0x5b, 0x62, 0x63, 0x00, 0x00, 0x00, 0x44, 0x45, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0xe8, 0xe9, 0x71, 0x72, 0x73, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x85, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe3, 0xe7, 0x65, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x58, 0xe4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x54, 0x00, 0x46, 0xe6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x00, 0x4a, 0x52, 0x4b, 0x00, 0x50, 0x00, 0x4f, 0x00, 0x4d, 0x51, 0x4e, 0x49, 0x4c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,};static void usb_mouse_event(void *opaque, int dx1, int dy1, int dz1, int buttons_state){ USBHIDState *hs = opaque; USBMouseState *s = &hs->ptr; s->dx += dx1; s->dy += dy1; s->dz += dz1; s->buttons_state = buttons_state; hs->changed = 1;}static void usb_tablet_event(void *opaque, int x, int y, int dz, int buttons_state){ USBHIDState *hs = opaque; USBMouseState *s = &hs->ptr; s->x = x; s->y = y; s->dz += dz; s->buttons_state = buttons_state; hs->changed = 1;}static void usb_keyboard_event(void *opaque, int keycode){ USBHIDState *hs = opaque; USBKeyboardState *s = &hs->kbd; uint8_t hid_code, key; int i; key = keycode & 0x7f; hid_code = usb_hid_usage_keys[key | ((s->modifiers >> 1) & (1 << 7))]; s->modifiers &= ~(1 << 8); hs->changed = 1; switch (hid_code) { case 0x00: return; case 0xe0: if (s->modifiers & (1 << 9)) { s->modifiers ^= 3 << 8; return; } case 0xe1 ... 0xe7: if (keycode & (1 << 7)) { s->modifiers &= ~(1 << (hid_code & 0x0f)); return; }
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -