⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 usb-hid.c

📁 xen虚拟机源代码安装包
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * 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 USBPointerEvent {    int xdx, ydy; /* relative iff it's a mouse, otherwise absolute */    int dz, buttons_state;} USBPointerEvent;#define QUEUELENSHIFT 4 /* 16 events should be enough for a triple-click */#define QUEUELEN (1u<<QUEUELENSHIFT)#define QUEUEINDEXMASK (QUEUELEN-1u)#define QUEUE_INCR(v) ((v)++, (v) &= QUEUEINDEXMASK)typedef struct USBPointerState {    USBPointerEvent queue[QUEUELEN];    unsigned head, tail; /* indices into circular queue */        int mouse_grabbed, xyrel;    QEMUPutMouseEntry *eh_entry;} USBPointerState;typedef struct USBKeyboardState {    uint16_t modifiers;    uint8_t leds;    uint8_t key[16];    int keys;    int changed;} USBKeyboardState;typedef struct USBHIDState {    USBDevice dev;    union {        USBPointerState ptr;        USBKeyboardState kbd;    };    int kind;    int protocol;    int idle;} 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 */        52, 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 */ 	0x04, 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,		/* Usage Page (Generic Desktop) */    0x09, 0x02,		/* Usage (Mouse) */    0xa1, 0x01,		/* Collection (Application) */    0x09, 0x01,		/*   Usage (Pointer) */    0xa1, 0x00,		/*   Collection (Physical) */    0x05, 0x09,		/*     Usage Page (Button) */    0x19, 0x01,		/*     Usage Minimum (1) */    0x29, 0x03,		/*     Usage Maximum (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, Variable, Absolute) */    0x95, 0x01,		/*     Report Count (1) */    0x75, 0x05,		/*     Report Size (5) */    0x81, 0x01,		/*     Input (Constant) */    0x05, 0x01,		/*     Usage Page (Generic Desktop) */    0x09, 0x30,		/*     Usage (X) */    0x09, 0x31,		/*     Usage (Y) */    0x09, 0x38,		/*     Usage (Wheel) */    0x15, 0x81,		/*     Logical Minimum (-0x7f) */    0x25, 0x7f,		/*     Logical Maximum (0x7f) */    0x75, 0x08,		/*     Report Size (8) */    0x95, 0x03,		/*     Report Count (3) */    0x81, 0x06,		/*     Input (Data, Variable, Relative) */    0xc0,		/*   End Collection */    0xc0,		/* End Collection */};static const uint8_t qemu_tablet_hid_report_descriptor[] = {    0x05, 0x01,		/* Usage Page (Generic Desktop) */    0x09, 0x01,		/* Usage (Pointer) */    0xa1, 0x01,		/* Collection (Application) */    0x09, 0x01,		/*   Usage (Pointer) */    0xa1, 0x00,		/*   Collection (Physical) */    0x05, 0x09,		/*     Usage Page (Button) */    0x19, 0x01,		/*     Usage Minimum (1) */    0x29, 0x03,		/*     Usage Maximum (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, Variable, Absolute) */    0x95, 0x01,		/*     Report Count (1) */    0x75, 0x05,		/*     Report Size (5) */    0x81, 0x01,		/*     Input (Constant) */    0x05, 0x01,		/*     Usage Page (Generic Desktop) */    0x09, 0x30,		/*     Usage (X) */    0x09, 0x31,		/*     Usage (Y) */    0x15, 0x00,		/*     Logical Minimum (0) */    0x26, 0xfe, 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, Variable, Absolute) */    0x05, 0x01,		/*     Usage Page (Generic Desktop) */    0x09, 0x38,		/*     Usage (Wheel) */    0x15, 0x81,		/*     Logical Minimum (-0x7f) */    0x25, 0x7f,		/*     Logical Maximum (0x7f) */    0x35, 0x00,		/*     Physical Minimum (same as logical) */    0x45, 0x00,		/*     Physical Maximum (same as logical) */    0x75, 0x08,		/*     Report Size (8) */    0x95, 0x01,		/*     Report Count (1) */    0x81, 0x06,		/*     Input (Data, Variable, Relative) */    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_pointer_event_clear(USBPointerEvent *e, int buttons) {    e->xdx = e->ydy = e->dz = 0;    e->buttons_state = buttons;}static void usb_pointer_event_combine(USBPointerEvent *e, int xyrel,				      int x1, int y1, int z1) {    if (xyrel) {	e->xdx += x1;	e->ydy += y1;    } else {	e->xdx = x1;	e->ydy = y1;    }    e->dz += z1;}static void usb_pointer_event(void *hs_v, int x1, int y1, int z1,			      int buttons_state) {    /* We combine events where feasible to keep the queue small.     * We shouldn't combine anything with the first event with     * a particular button state, as that would change the     * location of the button state change. */    USBHIDState *hs= hs_v;    USBPointerState *s = &hs->ptr;    unsigned use_slot= (s->tail-1) & QUEUEINDEXMASK;    unsigned previous_slot= (use_slot-1) & QUEUEINDEXMASK;    if (s->tail == s->head) {        use_slot= s->tail;        QUEUE_INCR(s->tail);        usb_pointer_event_clear(&s->queue[use_slot], buttons_state);    } else if (use_slot == s->head ||	s->queue[use_slot].buttons_state != buttons_state ||	s->queue[previous_slot].buttons_state != buttons_state) {	/* can't or shouldn't combine this event with previous one */	use_slot= s->tail;	QUEUE_INCR(s->tail);	if (use_slot == s->head) {	    /* queue full, oh well, discard something */	    s->head++;  s->head &= QUEUEINDEXMASK;	    /* but we preserve the relative motions */	    usb_pointer_event_combine(&s->queue[s->head], s->xyrel,				      s->queue[use_slot].xdx,				      s->queue[use_slot].ydy,				      s->queue[use_slot].dz);	}	usb_pointer_event_clear(&s->queue[use_slot], buttons_state);    }    usb_pointer_event_combine(&s->queue[use_slot],s->xyrel, x1,y1,z1);}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -