USB tablet support (Brad Campbell, Anthony Liguori)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1810 c046a42c-6fe2-441c-8c8c-71466251a162
This commit is contained in:
		
							parent
							
								
									6a15fd12ca
								
							
						
					
					
						commit
						09b26c5ec0
					
				
							
								
								
									
										2
									
								
								hw/ps2.c
								
								
								
								
							
							
						
						
									
										2
									
								
								hw/ps2.c
								
								
								
								
							| 
						 | 
				
			
			@ -560,7 +560,7 @@ void *ps2_mouse_init(void (*update_irq)(void *, int), void *update_arg)
 | 
			
		|||
    s->common.update_arg = update_arg;
 | 
			
		||||
    ps2_reset(&s->common);
 | 
			
		||||
    register_savevm("ps2mouse", 0, 2, ps2_mouse_save, ps2_mouse_load, s);
 | 
			
		||||
    qemu_add_mouse_event_handler(ps2_mouse_event, s);
 | 
			
		||||
    qemu_add_mouse_event_handler(ps2_mouse_event, s, 0);
 | 
			
		||||
    qemu_register_reset(ps2_reset, &s->common);
 | 
			
		||||
    return s;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										234
									
								
								hw/usb-hid.c
								
								
								
								
							
							
						
						
									
										234
									
								
								hw/usb-hid.c
								
								
								
								
							| 
						 | 
				
			
			@ -30,9 +30,15 @@
 | 
			
		|||
#define SET_IDLE     0x210a
 | 
			
		||||
#define SET_PROTOCOL 0x210b
 | 
			
		||||
 | 
			
		||||
#define USB_MOUSE  1
 | 
			
		||||
#define USB_TABLET 2
 | 
			
		||||
 | 
			
		||||
typedef struct USBMouseState {
 | 
			
		||||
    USBDevice dev;
 | 
			
		||||
    int dx, dy, dz, buttons_state;
 | 
			
		||||
    int x, y;
 | 
			
		||||
    int kind;
 | 
			
		||||
    int mouse_grabbed;
 | 
			
		||||
} USBMouseState;
 | 
			
		||||
 | 
			
		||||
/* mostly the same values as the Bochs USB Mouse device */
 | 
			
		||||
| 
						 | 
				
			
			@ -93,14 +99,6 @@ static const uint8_t qemu_mouse_config_descriptor[] = {
 | 
			
		|||
	0x02,       /*  u8  if_bInterfaceProtocol; [usb1.1 or single tt] */
 | 
			
		||||
	0x05,       /*  u8  if_iInterface; */
 | 
			
		||||
     
 | 
			
		||||
	/* 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) */
 | 
			
		||||
 | 
			
		||||
        /* HID descriptor */
 | 
			
		||||
        0x09,        /*  u8  bLength; */
 | 
			
		||||
        0x21,        /*  u8 bDescriptorType; */
 | 
			
		||||
| 
						 | 
				
			
			@ -109,6 +107,69 @@ static const uint8_t qemu_mouse_config_descriptor[] = {
 | 
			
		|||
        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; */
 | 
			
		||||
	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] */
 | 
			
		||||
	0x05,       /*  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; */
 | 
			
		||||
	0x03,       /*  u8  ep_bInterval; (255ms -- usb 2.0 spec) */
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static const uint8_t qemu_mouse_hid_report_descriptor[] = {
 | 
			
		||||
| 
						 | 
				
			
			@ -121,6 +182,46 @@ static const uint8_t qemu_mouse_hid_report_descriptor[] = {
 | 
			
		|||
    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 void usb_mouse_event(void *opaque,
 | 
			
		||||
                            int dx1, int dy1, int dz1, int buttons_state)
 | 
			
		||||
{
 | 
			
		||||
| 
						 | 
				
			
			@ -132,6 +233,17 @@ static void usb_mouse_event(void *opaque,
 | 
			
		|||
    s->buttons_state = buttons_state;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void usb_tablet_event(void *opaque,
 | 
			
		||||
			     int x, int y, int dz, int buttons_state)
 | 
			
		||||
{
 | 
			
		||||
    USBMouseState *s = opaque;
 | 
			
		||||
 | 
			
		||||
    s->x = x;
 | 
			
		||||
    s->y = y;
 | 
			
		||||
    s->dz += dz;
 | 
			
		||||
    s->buttons_state = buttons_state;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static inline int int_clamp(int val, int vmin, int vmax)
 | 
			
		||||
{
 | 
			
		||||
    if (val < vmin)
 | 
			
		||||
| 
						 | 
				
			
			@ -146,6 +258,11 @@ static int usb_mouse_poll(USBMouseState *s, uint8_t *buf, int len)
 | 
			
		|||
{
 | 
			
		||||
    int dx, dy, dz, b, l;
 | 
			
		||||
 | 
			
		||||
    if (!s->mouse_grabbed) {
 | 
			
		||||
	qemu_add_mouse_event_handler(usb_mouse_event, s, 0);
 | 
			
		||||
	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);
 | 
			
		||||
| 
						 | 
				
			
			@ -173,6 +290,39 @@ static int usb_mouse_poll(USBMouseState *s, uint8_t *buf, int len)
 | 
			
		|||
    return l;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int usb_tablet_poll(USBMouseState *s, uint8_t *buf, int len)
 | 
			
		||||
{
 | 
			
		||||
    int dz, b, l;
 | 
			
		||||
 | 
			
		||||
    if (!s->mouse_grabbed) {
 | 
			
		||||
	qemu_add_mouse_event_handler(usb_tablet_event, s, 1);
 | 
			
		||||
	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 void usb_mouse_handle_reset(USBDevice *dev)
 | 
			
		||||
{
 | 
			
		||||
    USBMouseState *s = (USBMouseState *)dev;
 | 
			
		||||
| 
						 | 
				
			
			@ -180,6 +330,8 @@ static void usb_mouse_handle_reset(USBDevice *dev)
 | 
			
		|||
    s->dx = 0;
 | 
			
		||||
    s->dy = 0;
 | 
			
		||||
    s->dz = 0;
 | 
			
		||||
    s->x = 0;
 | 
			
		||||
    s->y = 0;
 | 
			
		||||
    s->buttons_state = 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -187,7 +339,7 @@ static int usb_mouse_handle_control(USBDevice *dev, int request, int value,
 | 
			
		|||
                                  int index, int length, uint8_t *data)
 | 
			
		||||
{
 | 
			
		||||
    USBMouseState *s = (USBMouseState *)dev;
 | 
			
		||||
    int ret;
 | 
			
		||||
    int ret = 0;
 | 
			
		||||
 | 
			
		||||
    switch(request) {
 | 
			
		||||
    case DeviceRequest | USB_REQ_GET_STATUS:
 | 
			
		||||
| 
						 | 
				
			
			@ -224,9 +376,15 @@ static int usb_mouse_handle_control(USBDevice *dev, int request, int value,
 | 
			
		|||
            ret = sizeof(qemu_mouse_dev_descriptor);
 | 
			
		||||
            break;
 | 
			
		||||
        case USB_DT_CONFIG:
 | 
			
		||||
            memcpy(data, qemu_mouse_config_descriptor, 
 | 
			
		||||
                   sizeof(qemu_mouse_config_descriptor));
 | 
			
		||||
            ret = sizeof(qemu_mouse_config_descriptor);
 | 
			
		||||
	    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);
 | 
			
		||||
	    }		
 | 
			
		||||
            break;
 | 
			
		||||
        case USB_DT_STRING:
 | 
			
		||||
            switch(value & 0xff) {
 | 
			
		||||
| 
						 | 
				
			
			@ -244,7 +402,10 @@ static int usb_mouse_handle_control(USBDevice *dev, int request, int value,
 | 
			
		|||
                break;
 | 
			
		||||
            case 2:
 | 
			
		||||
                /* product description */
 | 
			
		||||
                ret = set_usb_string(data, "QEMU USB Mouse");
 | 
			
		||||
		if (s->kind == USB_MOUSE)
 | 
			
		||||
		    ret = set_usb_string(data, "QEMU USB Mouse");
 | 
			
		||||
		else if (s->kind == USB_TABLET)
 | 
			
		||||
		    ret = set_usb_string(data, "QEMU USB Tablet");
 | 
			
		||||
                break;
 | 
			
		||||
            case 3:
 | 
			
		||||
                /* vendor description */
 | 
			
		||||
| 
						 | 
				
			
			@ -282,16 +443,25 @@ static int usb_mouse_handle_control(USBDevice *dev, int request, int value,
 | 
			
		|||
    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;
 | 
			
		||||
	    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);
 | 
			
		||||
	    }
 | 
			
		||||
	    break;
 | 
			
		||||
        default:
 | 
			
		||||
            goto fail;
 | 
			
		||||
        }
 | 
			
		||||
        break;
 | 
			
		||||
    case GET_REPORT:
 | 
			
		||||
        ret = usb_mouse_poll(s, data, length);
 | 
			
		||||
	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);
 | 
			
		||||
        break;
 | 
			
		||||
    case SET_IDLE:
 | 
			
		||||
        ret = 0;
 | 
			
		||||
| 
						 | 
				
			
			@ -308,12 +478,15 @@ static int usb_mouse_handle_data(USBDevice *dev, int pid,
 | 
			
		|||
                                 uint8_t devep, uint8_t *data, int len)
 | 
			
		||||
{
 | 
			
		||||
    USBMouseState *s = (USBMouseState *)dev;
 | 
			
		||||
    int ret;
 | 
			
		||||
    int ret = 0;
 | 
			
		||||
 | 
			
		||||
    switch(pid) {
 | 
			
		||||
    case USB_TOKEN_IN:
 | 
			
		||||
        if (devep == 1) {
 | 
			
		||||
            ret = usb_mouse_poll(s, data, len);
 | 
			
		||||
	    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;
 | 
			
		||||
        }
 | 
			
		||||
| 
						 | 
				
			
			@ -327,6 +500,24 @@ static int usb_mouse_handle_data(USBDevice *dev, int pid,
 | 
			
		|||
    return ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
USBDevice *usb_tablet_init(void)
 | 
			
		||||
{
 | 
			
		||||
    USBMouseState *s;
 | 
			
		||||
 | 
			
		||||
    s = qemu_mallocz(sizeof(USBMouseState));
 | 
			
		||||
    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_mouse_handle_control;
 | 
			
		||||
    s->dev.handle_data = usb_mouse_handle_data;
 | 
			
		||||
    s->kind = USB_TABLET;
 | 
			
		||||
 | 
			
		||||
    return (USBDevice *)s;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
USBDevice *usb_mouse_init(void)
 | 
			
		||||
{
 | 
			
		||||
    USBMouseState *s;
 | 
			
		||||
| 
						 | 
				
			
			@ -340,8 +531,7 @@ USBDevice *usb_mouse_init(void)
 | 
			
		|||
    s->dev.handle_reset = usb_mouse_handle_reset;
 | 
			
		||||
    s->dev.handle_control = usb_mouse_handle_control;
 | 
			
		||||
    s->dev.handle_data = usb_mouse_handle_data;
 | 
			
		||||
 | 
			
		||||
    qemu_add_mouse_event_handler(usb_mouse_event, s);
 | 
			
		||||
    s->kind = USB_MOUSE;
 | 
			
		||||
 | 
			
		||||
    return (USBDevice *)s;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										1
									
								
								hw/usb.h
								
								
								
								
							
							
						
						
									
										1
									
								
								hw/usb.h
								
								
								
								
							| 
						 | 
				
			
			@ -163,3 +163,4 @@ void usb_host_info(void);
 | 
			
		|||
 | 
			
		||||
/* usb-hid.c */
 | 
			
		||||
USBDevice *usb_mouse_init(void);
 | 
			
		||||
USBDevice *usb_tablet_init(void);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										50
									
								
								sdl.c
								
								
								
								
							
							
						
						
									
										50
									
								
								sdl.c
								
								
								
								
							| 
						 | 
				
			
			@ -39,6 +39,10 @@ static int gui_keysym;
 | 
			
		|||
static int gui_fullscreen_initial_grab;
 | 
			
		||||
static int gui_grab_code = KMOD_LALT | KMOD_LCTRL;
 | 
			
		||||
static uint8_t modifiers_state[256];
 | 
			
		||||
static int width, height;
 | 
			
		||||
static SDL_Cursor *sdl_cursor_normal;
 | 
			
		||||
static SDL_Cursor *sdl_cursor_hidden;
 | 
			
		||||
static int absolute_enabled = 0;
 | 
			
		||||
 | 
			
		||||
static void sdl_update(DisplayState *ds, int x, int y, int w, int h)
 | 
			
		||||
{
 | 
			
		||||
| 
						 | 
				
			
			@ -56,6 +60,9 @@ static void sdl_resize(DisplayState *ds, int w, int h)
 | 
			
		|||
    if (gui_fullscreen)
 | 
			
		||||
        flags |= SDL_FULLSCREEN;
 | 
			
		||||
 | 
			
		||||
    width = w;
 | 
			
		||||
    height = h;
 | 
			
		||||
 | 
			
		||||
 again:
 | 
			
		||||
    screen = SDL_SetVideoMode(w, h, 0, flags);
 | 
			
		||||
    if (!screen) {
 | 
			
		||||
| 
						 | 
				
			
			@ -271,9 +278,21 @@ static void sdl_update_caption(void)
 | 
			
		|||
    SDL_WM_SetCaption(buf, "QEMU");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void sdl_hide_cursor(void)
 | 
			
		||||
{
 | 
			
		||||
    SDL_SetCursor(sdl_cursor_hidden);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void sdl_show_cursor(void)
 | 
			
		||||
{
 | 
			
		||||
    if (!kbd_mouse_is_absolute()) {
 | 
			
		||||
	SDL_SetCursor(sdl_cursor_normal);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void sdl_grab_start(void)
 | 
			
		||||
{
 | 
			
		||||
    SDL_ShowCursor(0);
 | 
			
		||||
    sdl_hide_cursor();
 | 
			
		||||
    SDL_WM_GrabInput(SDL_GRAB_ON);
 | 
			
		||||
    /* dummy read to avoid moving the mouse */
 | 
			
		||||
    SDL_GetRelativeMouseState(NULL, NULL);
 | 
			
		||||
| 
						 | 
				
			
			@ -284,7 +303,7 @@ static void sdl_grab_start(void)
 | 
			
		|||
static void sdl_grab_end(void)
 | 
			
		||||
{
 | 
			
		||||
    SDL_WM_GrabInput(SDL_GRAB_OFF);
 | 
			
		||||
    SDL_ShowCursor(1);
 | 
			
		||||
    sdl_show_cursor();
 | 
			
		||||
    gui_grab = 0;
 | 
			
		||||
    sdl_update_caption();
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -300,6 +319,21 @@ static void sdl_send_mouse_event(int dz)
 | 
			
		|||
        buttons |= MOUSE_EVENT_RBUTTON;
 | 
			
		||||
    if (state & SDL_BUTTON(SDL_BUTTON_MIDDLE))
 | 
			
		||||
        buttons |= MOUSE_EVENT_MBUTTON;
 | 
			
		||||
 | 
			
		||||
    if (kbd_mouse_is_absolute()) {
 | 
			
		||||
	if (!absolute_enabled) {
 | 
			
		||||
	    sdl_hide_cursor();
 | 
			
		||||
	    if (gui_grab) {
 | 
			
		||||
		sdl_grab_end();
 | 
			
		||||
	    }
 | 
			
		||||
	    absolute_enabled = 1;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	SDL_GetMouseState(&dx, &dy);
 | 
			
		||||
	dx = dx * 0x7FFF / width;
 | 
			
		||||
	dy = dy * 0x7FFF / height;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    kbd_mouse_event(dx, dy, dz, buttons);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -423,7 +457,7 @@ static void sdl_refresh(DisplayState *ds)
 | 
			
		|||
            qemu_system_shutdown_request();
 | 
			
		||||
            break;
 | 
			
		||||
        case SDL_MOUSEMOTION:
 | 
			
		||||
            if (gui_grab) {
 | 
			
		||||
            if (gui_grab || kbd_mouse_is_absolute()) {
 | 
			
		||||
                sdl_send_mouse_event(0);
 | 
			
		||||
            }
 | 
			
		||||
            break;
 | 
			
		||||
| 
						 | 
				
			
			@ -431,7 +465,7 @@ static void sdl_refresh(DisplayState *ds)
 | 
			
		|||
        case SDL_MOUSEBUTTONUP:
 | 
			
		||||
            {
 | 
			
		||||
                SDL_MouseButtonEvent *bev = &ev->button;
 | 
			
		||||
                if (!gui_grab) {
 | 
			
		||||
                if (!gui_grab && !kbd_mouse_is_absolute()) {
 | 
			
		||||
                    if (ev->type == SDL_MOUSEBUTTONDOWN &&
 | 
			
		||||
                        (bev->state & SDL_BUTTON_LMASK)) {
 | 
			
		||||
                        /* start grabbing all events */
 | 
			
		||||
| 
						 | 
				
			
			@ -441,9 +475,9 @@ static void sdl_refresh(DisplayState *ds)
 | 
			
		|||
                    int dz;
 | 
			
		||||
                    dz = 0;
 | 
			
		||||
#ifdef SDL_BUTTON_WHEELUP
 | 
			
		||||
                    if (bev->button == SDL_BUTTON_WHEELUP) {
 | 
			
		||||
                    if (bev->button == SDL_BUTTON_WHEELUP && ev->type == SDL_MOUSEBUTTONDOWN) {
 | 
			
		||||
                        dz = -1;
 | 
			
		||||
                    } else if (bev->button == SDL_BUTTON_WHEELDOWN) {
 | 
			
		||||
                    } else if (bev->button == SDL_BUTTON_WHEELDOWN && ev->type == SDL_MOUSEBUTTONDOWN) {
 | 
			
		||||
                        dz = 1;
 | 
			
		||||
                    }
 | 
			
		||||
#endif               
 | 
			
		||||
| 
						 | 
				
			
			@ -471,6 +505,7 @@ static void sdl_cleanup(void)
 | 
			
		|||
void sdl_display_init(DisplayState *ds, int full_screen)
 | 
			
		||||
{
 | 
			
		||||
    int flags;
 | 
			
		||||
    uint8_t data = 0;
 | 
			
		||||
 | 
			
		||||
#if defined(__APPLE__)
 | 
			
		||||
    /* always use generic keymaps */
 | 
			
		||||
| 
						 | 
				
			
			@ -504,6 +539,9 @@ void sdl_display_init(DisplayState *ds, int full_screen)
 | 
			
		|||
    SDL_EnableUNICODE(1);
 | 
			
		||||
    gui_grab = 0;
 | 
			
		||||
 | 
			
		||||
    sdl_cursor_hidden = SDL_CreateCursor(&data, &data, 8, 1, 0, 0);
 | 
			
		||||
    sdl_cursor_normal = SDL_GetCursor();
 | 
			
		||||
 | 
			
		||||
    atexit(sdl_cleanup);
 | 
			
		||||
    if (full_screen) {
 | 
			
		||||
        gui_fullscreen = 1;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										13
									
								
								vl.c
								
								
								
								
							
							
						
						
									
										13
									
								
								vl.c
								
								
								
								
							| 
						 | 
				
			
			@ -474,6 +474,7 @@ static QEMUPutKBDEvent *qemu_put_kbd_event;
 | 
			
		|||
static void *qemu_put_kbd_event_opaque;
 | 
			
		||||
static QEMUPutMouseEvent *qemu_put_mouse_event;
 | 
			
		||||
static void *qemu_put_mouse_event_opaque;
 | 
			
		||||
static int qemu_put_mouse_event_absolute;
 | 
			
		||||
 | 
			
		||||
void qemu_add_kbd_event_handler(QEMUPutKBDEvent *func, void *opaque)
 | 
			
		||||
{
 | 
			
		||||
| 
						 | 
				
			
			@ -481,10 +482,11 @@ void qemu_add_kbd_event_handler(QEMUPutKBDEvent *func, void *opaque)
 | 
			
		|||
    qemu_put_kbd_event = func;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void qemu_add_mouse_event_handler(QEMUPutMouseEvent *func, void *opaque)
 | 
			
		||||
void qemu_add_mouse_event_handler(QEMUPutMouseEvent *func, void *opaque, int absolute)
 | 
			
		||||
{
 | 
			
		||||
    qemu_put_mouse_event_opaque = opaque;
 | 
			
		||||
    qemu_put_mouse_event = func;
 | 
			
		||||
    qemu_put_mouse_event_absolute = absolute;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void kbd_put_keycode(int keycode)
 | 
			
		||||
| 
						 | 
				
			
			@ -502,6 +504,11 @@ void kbd_mouse_event(int dx, int dy, int dz, int buttons_state)
 | 
			
		|||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int kbd_mouse_is_absolute(void)
 | 
			
		||||
{
 | 
			
		||||
    return qemu_put_mouse_event_absolute;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/***********************************************************/
 | 
			
		||||
/* timers */
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -3242,6 +3249,10 @@ static int usb_device_add(const char *devname)
 | 
			
		|||
        dev = usb_mouse_init();
 | 
			
		||||
        if (!dev)
 | 
			
		||||
            return -1;
 | 
			
		||||
    } else if (!strcmp(devname, "tablet")) {
 | 
			
		||||
	dev = usb_tablet_init();
 | 
			
		||||
	if (!dev)
 | 
			
		||||
	    return -1;
 | 
			
		||||
    } else {
 | 
			
		||||
        return -1;
 | 
			
		||||
    }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										3
									
								
								vl.h
								
								
								
								
							
							
						
						
									
										3
									
								
								vl.h
								
								
								
								
							| 
						 | 
				
			
			@ -158,10 +158,11 @@ typedef void QEMUPutKBDEvent(void *opaque, int keycode);
 | 
			
		|||
typedef void QEMUPutMouseEvent(void *opaque, int dx, int dy, int dz, int buttons_state);
 | 
			
		||||
 | 
			
		||||
void qemu_add_kbd_event_handler(QEMUPutKBDEvent *func, void *opaque);
 | 
			
		||||
void qemu_add_mouse_event_handler(QEMUPutMouseEvent *func, void *opaque);
 | 
			
		||||
void qemu_add_mouse_event_handler(QEMUPutMouseEvent *func, void *opaque, int absolute);
 | 
			
		||||
 | 
			
		||||
void kbd_put_keycode(int keycode);
 | 
			
		||||
void kbd_mouse_event(int dx, int dy, int dz, int buttons_state);
 | 
			
		||||
int kbd_mouse_is_absolute(void);
 | 
			
		||||
 | 
			
		||||
/* keysym is a unicode code except for special keys (see QEMU_KEY_xxx
 | 
			
		||||
   constants) */
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue