Commit 09b26c5ec06ff7531a2a2a7b1146011c87285f81

Authored by bellard
1 parent 6a15fd12

USB tablet support (Brad Campbell, Anthony Liguori)


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1810 c046a42c-6fe2-441c-8c8c-71466251a162
hw/ps2.c
@@ -560,7 +560,7 @@ void *ps2_mouse_init(void (*update_irq)(void *, int), void *update_arg) @@ -560,7 +560,7 @@ void *ps2_mouse_init(void (*update_irq)(void *, int), void *update_arg)
560 s->common.update_arg = update_arg; 560 s->common.update_arg = update_arg;
561 ps2_reset(&s->common); 561 ps2_reset(&s->common);
562 register_savevm("ps2mouse", 0, 2, ps2_mouse_save, ps2_mouse_load, s); 562 register_savevm("ps2mouse", 0, 2, ps2_mouse_save, ps2_mouse_load, s);
563 - qemu_add_mouse_event_handler(ps2_mouse_event, s); 563 + qemu_add_mouse_event_handler(ps2_mouse_event, s, 0);
564 qemu_register_reset(ps2_reset, &s->common); 564 qemu_register_reset(ps2_reset, &s->common);
565 return s; 565 return s;
566 } 566 }
hw/usb-hid.c
@@ -30,9 +30,15 @@ @@ -30,9 +30,15 @@
30 #define SET_IDLE 0x210a 30 #define SET_IDLE 0x210a
31 #define SET_PROTOCOL 0x210b 31 #define SET_PROTOCOL 0x210b
32 32
  33 +#define USB_MOUSE 1
  34 +#define USB_TABLET 2
  35 +
33 typedef struct USBMouseState { 36 typedef struct USBMouseState {
34 USBDevice dev; 37 USBDevice dev;
35 int dx, dy, dz, buttons_state; 38 int dx, dy, dz, buttons_state;
  39 + int x, y;
  40 + int kind;
  41 + int mouse_grabbed;
36 } USBMouseState; 42 } USBMouseState;
37 43
38 /* mostly the same values as the Bochs USB Mouse device */ 44 /* mostly the same values as the Bochs USB Mouse device */
@@ -93,6 +99,15 @@ static const uint8_t qemu_mouse_config_descriptor[] = { @@ -93,6 +99,15 @@ static const uint8_t qemu_mouse_config_descriptor[] = {
93 0x02, /* u8 if_bInterfaceProtocol; [usb1.1 or single tt] */ 99 0x02, /* u8 if_bInterfaceProtocol; [usb1.1 or single tt] */
94 0x05, /* u8 if_iInterface; */ 100 0x05, /* u8 if_iInterface; */
95 101
  102 + /* HID descriptor */
  103 + 0x09, /* u8 bLength; */
  104 + 0x21, /* u8 bDescriptorType; */
  105 + 0x01, 0x00, /* u16 HID_class */
  106 + 0x00, /* u8 country_code */
  107 + 0x01, /* u8 num_descriptors */
  108 + 0x22, /* u8 type; Report */
  109 + 50, 0, /* u16 len */
  110 +
96 /* one endpoint (status change endpoint) */ 111 /* one endpoint (status change endpoint) */
97 0x07, /* u8 ep_bLength; */ 112 0x07, /* u8 ep_bLength; */
98 0x05, /* u8 ep_bDescriptorType; Endpoint */ 113 0x05, /* u8 ep_bDescriptorType; Endpoint */
@@ -100,6 +115,44 @@ static const uint8_t qemu_mouse_config_descriptor[] = { @@ -100,6 +115,44 @@ static const uint8_t qemu_mouse_config_descriptor[] = {
100 0x03, /* u8 ep_bmAttributes; Interrupt */ 115 0x03, /* u8 ep_bmAttributes; Interrupt */
101 0x03, 0x00, /* u16 ep_wMaxPacketSize; */ 116 0x03, 0x00, /* u16 ep_wMaxPacketSize; */
102 0x0a, /* u8 ep_bInterval; (255ms -- usb 2.0 spec) */ 117 0x0a, /* u8 ep_bInterval; (255ms -- usb 2.0 spec) */
  118 +};
  119 +
  120 +static const uint8_t qemu_tablet_config_descriptor[] = {
  121 + /* one configuration */
  122 + 0x09, /* u8 bLength; */
  123 + 0x02, /* u8 bDescriptorType; Configuration */
  124 + 0x22, 0x00, /* u16 wTotalLength; */
  125 + 0x01, /* u8 bNumInterfaces; (1) */
  126 + 0x01, /* u8 bConfigurationValue; */
  127 + 0x04, /* u8 iConfiguration; */
  128 + 0xa0, /* u8 bmAttributes;
  129 + Bit 7: must be set,
  130 + 6: Self-powered,
  131 + 5: Remote wakeup,
  132 + 4..0: resvd */
  133 + 50, /* u8 MaxPower; */
  134 +
  135 + /* USB 1.1:
  136 + * USB 2.0, single TT organization (mandatory):
  137 + * one interface, protocol 0
  138 + *
  139 + * USB 2.0, multiple TT organization (optional):
  140 + * two interfaces, protocols 1 (like single TT)
  141 + * and 2 (multiple TT mode) ... config is
  142 + * sometimes settable
  143 + * NOT IMPLEMENTED
  144 + */
  145 +
  146 + /* one interface */
  147 + 0x09, /* u8 if_bLength; */
  148 + 0x04, /* u8 if_bDescriptorType; Interface */
  149 + 0x00, /* u8 if_bInterfaceNumber; */
  150 + 0x00, /* u8 if_bAlternateSetting; */
  151 + 0x01, /* u8 if_bNumEndpoints; */
  152 + 0x03, /* u8 if_bInterfaceClass; */
  153 + 0x01, /* u8 if_bInterfaceSubClass; */
  154 + 0x02, /* u8 if_bInterfaceProtocol; [usb1.1 or single tt] */
  155 + 0x05, /* u8 if_iInterface; */
103 156
104 /* HID descriptor */ 157 /* HID descriptor */
105 0x09, /* u8 bLength; */ 158 0x09, /* u8 bLength; */
@@ -108,7 +161,15 @@ static const uint8_t qemu_mouse_config_descriptor[] = { @@ -108,7 +161,15 @@ static const uint8_t qemu_mouse_config_descriptor[] = {
108 0x00, /* u8 country_code */ 161 0x00, /* u8 country_code */
109 0x01, /* u8 num_descriptors */ 162 0x01, /* u8 num_descriptors */
110 0x22, /* u8 type; Report */ 163 0x22, /* u8 type; Report */
111 - 50, 0, /* u16 len */ 164 + 74, 0, /* u16 len */
  165 +
  166 + /* one endpoint (status change endpoint) */
  167 + 0x07, /* u8 ep_bLength; */
  168 + 0x05, /* u8 ep_bDescriptorType; Endpoint */
  169 + 0x81, /* u8 ep_bEndpointAddress; IN Endpoint 1 */
  170 + 0x03, /* u8 ep_bmAttributes; Interrupt */
  171 + 0x08, 0x00, /* u16 ep_wMaxPacketSize; */
  172 + 0x03, /* u8 ep_bInterval; (255ms -- usb 2.0 spec) */
112 }; 173 };
113 174
114 static const uint8_t qemu_mouse_hid_report_descriptor[] = { 175 static const uint8_t qemu_mouse_hid_report_descriptor[] = {
@@ -121,6 +182,46 @@ static const uint8_t qemu_mouse_hid_report_descriptor[] = { @@ -121,6 +182,46 @@ static const uint8_t qemu_mouse_hid_report_descriptor[] = {
121 0xC0, 0xC0, 182 0xC0, 0xC0,
122 }; 183 };
123 184
  185 +static const uint8_t qemu_tablet_hid_report_descriptor[] = {
  186 + 0x05, 0x01, /* Usage Page Generic Desktop */
  187 + 0x09, 0x01, /* Usage Mouse */
  188 + 0xA1, 0x01, /* Collection Application */
  189 + 0x09, 0x01, /* Usage Pointer */
  190 + 0xA1, 0x00, /* Collection Physical */
  191 + 0x05, 0x09, /* Usage Page Button */
  192 + 0x19, 0x01, /* Usage Minimum Button 1 */
  193 + 0x29, 0x03, /* Usage Maximum Button 3 */
  194 + 0x15, 0x00, /* Logical Minimum 0 */
  195 + 0x25, 0x01, /* Logical Maximum 1 */
  196 + 0x95, 0x03, /* Report Count 3 */
  197 + 0x75, 0x01, /* Report Size 1 */
  198 + 0x81, 0x02, /* Input (Data, Var, Abs) */
  199 + 0x95, 0x01, /* Report Count 1 */
  200 + 0x75, 0x05, /* Report Size 5 */
  201 + 0x81, 0x01, /* Input (Cnst, Var, Abs) */
  202 + 0x05, 0x01, /* Usage Page Generic Desktop */
  203 + 0x09, 0x30, /* Usage X */
  204 + 0x09, 0x31, /* Usage Y */
  205 + 0x15, 0x00, /* Logical Minimum 0 */
  206 + 0x26, 0xFF, 0x7F, /* Logical Maximum 0x7fff */
  207 + 0x35, 0x00, /* Physical Minimum 0 */
  208 + 0x46, 0xFE, 0x7F, /* Physical Maximum 0x7fff */
  209 + 0x75, 0x10, /* Report Size 16 */
  210 + 0x95, 0x02, /* Report Count 2 */
  211 + 0x81, 0x02, /* Input (Data, Var, Abs) */
  212 + 0x05, 0x01, /* Usage Page Generic Desktop */
  213 + 0x09, 0x38, /* Usage Wheel */
  214 + 0x15, 0x81, /* Logical Minimum -127 */
  215 + 0x25, 0x7F, /* Logical Maximum 127 */
  216 + 0x35, 0x00, /* Physical Minimum 0 (same as logical) */
  217 + 0x45, 0x00, /* Physical Maximum 0 (same as logical) */
  218 + 0x75, 0x08, /* Report Size 8 */
  219 + 0x95, 0x01, /* Report Count 1 */
  220 + 0x81, 0x02, /* Input (Data, Var, Rel) */
  221 + 0xC0, /* End Collection */
  222 + 0xC0, /* End Collection */
  223 +};
  224 +
124 static void usb_mouse_event(void *opaque, 225 static void usb_mouse_event(void *opaque,
125 int dx1, int dy1, int dz1, int buttons_state) 226 int dx1, int dy1, int dz1, int buttons_state)
126 { 227 {
@@ -132,6 +233,17 @@ static void usb_mouse_event(void *opaque, @@ -132,6 +233,17 @@ static void usb_mouse_event(void *opaque,
132 s->buttons_state = buttons_state; 233 s->buttons_state = buttons_state;
133 } 234 }
134 235
  236 +static void usb_tablet_event(void *opaque,
  237 + int x, int y, int dz, int buttons_state)
  238 +{
  239 + USBMouseState *s = opaque;
  240 +
  241 + s->x = x;
  242 + s->y = y;
  243 + s->dz += dz;
  244 + s->buttons_state = buttons_state;
  245 +}
  246 +
135 static inline int int_clamp(int val, int vmin, int vmax) 247 static inline int int_clamp(int val, int vmin, int vmax)
136 { 248 {
137 if (val < vmin) 249 if (val < vmin)
@@ -146,6 +258,11 @@ static int usb_mouse_poll(USBMouseState *s, uint8_t *buf, int len) @@ -146,6 +258,11 @@ static int usb_mouse_poll(USBMouseState *s, uint8_t *buf, int len)
146 { 258 {
147 int dx, dy, dz, b, l; 259 int dx, dy, dz, b, l;
148 260
  261 + if (!s->mouse_grabbed) {
  262 + qemu_add_mouse_event_handler(usb_mouse_event, s, 0);
  263 + s->mouse_grabbed = 1;
  264 + }
  265 +
149 dx = int_clamp(s->dx, -128, 127); 266 dx = int_clamp(s->dx, -128, 127);
150 dy = int_clamp(s->dy, -128, 127); 267 dy = int_clamp(s->dy, -128, 127);
151 dz = int_clamp(s->dz, -128, 127); 268 dz = int_clamp(s->dz, -128, 127);
@@ -173,6 +290,39 @@ static int usb_mouse_poll(USBMouseState *s, uint8_t *buf, int len) @@ -173,6 +290,39 @@ static int usb_mouse_poll(USBMouseState *s, uint8_t *buf, int len)
173 return l; 290 return l;
174 } 291 }
175 292
  293 +static int usb_tablet_poll(USBMouseState *s, uint8_t *buf, int len)
  294 +{
  295 + int dz, b, l;
  296 +
  297 + if (!s->mouse_grabbed) {
  298 + qemu_add_mouse_event_handler(usb_tablet_event, s, 1);
  299 + s->mouse_grabbed = 1;
  300 + }
  301 +
  302 + dz = int_clamp(s->dz, -128, 127);
  303 + s->dz -= dz;
  304 +
  305 + /* Appears we have to invert the wheel direction */
  306 + dz = 0 - dz;
  307 + b = 0;
  308 + if (s->buttons_state & MOUSE_EVENT_LBUTTON)
  309 + b |= 0x01;
  310 + if (s->buttons_state & MOUSE_EVENT_RBUTTON)
  311 + b |= 0x02;
  312 + if (s->buttons_state & MOUSE_EVENT_MBUTTON)
  313 + b |= 0x04;
  314 +
  315 + buf[0] = b;
  316 + buf[1] = s->x & 0xff;
  317 + buf[2] = s->x >> 8;
  318 + buf[3] = s->y & 0xff;
  319 + buf[4] = s->y >> 8;
  320 + buf[5] = dz;
  321 + l = 6;
  322 +
  323 + return l;
  324 +}
  325 +
176 static void usb_mouse_handle_reset(USBDevice *dev) 326 static void usb_mouse_handle_reset(USBDevice *dev)
177 { 327 {
178 USBMouseState *s = (USBMouseState *)dev; 328 USBMouseState *s = (USBMouseState *)dev;
@@ -180,6 +330,8 @@ static void usb_mouse_handle_reset(USBDevice *dev) @@ -180,6 +330,8 @@ static void usb_mouse_handle_reset(USBDevice *dev)
180 s->dx = 0; 330 s->dx = 0;
181 s->dy = 0; 331 s->dy = 0;
182 s->dz = 0; 332 s->dz = 0;
  333 + s->x = 0;
  334 + s->y = 0;
183 s->buttons_state = 0; 335 s->buttons_state = 0;
184 } 336 }
185 337
@@ -187,7 +339,7 @@ static int usb_mouse_handle_control(USBDevice *dev, int request, int value, @@ -187,7 +339,7 @@ static int usb_mouse_handle_control(USBDevice *dev, int request, int value,
187 int index, int length, uint8_t *data) 339 int index, int length, uint8_t *data)
188 { 340 {
189 USBMouseState *s = (USBMouseState *)dev; 341 USBMouseState *s = (USBMouseState *)dev;
190 - int ret; 342 + int ret = 0;
191 343
192 switch(request) { 344 switch(request) {
193 case DeviceRequest | USB_REQ_GET_STATUS: 345 case DeviceRequest | USB_REQ_GET_STATUS:
@@ -224,9 +376,15 @@ static int usb_mouse_handle_control(USBDevice *dev, int request, int value, @@ -224,9 +376,15 @@ static int usb_mouse_handle_control(USBDevice *dev, int request, int value,
224 ret = sizeof(qemu_mouse_dev_descriptor); 376 ret = sizeof(qemu_mouse_dev_descriptor);
225 break; 377 break;
226 case USB_DT_CONFIG: 378 case USB_DT_CONFIG:
227 - memcpy(data, qemu_mouse_config_descriptor,  
228 - sizeof(qemu_mouse_config_descriptor));  
229 - ret = sizeof(qemu_mouse_config_descriptor); 379 + if (s->kind == USB_MOUSE) {
  380 + memcpy(data, qemu_mouse_config_descriptor,
  381 + sizeof(qemu_mouse_config_descriptor));
  382 + ret = sizeof(qemu_mouse_config_descriptor);
  383 + } else if (s->kind == USB_TABLET) {
  384 + memcpy(data, qemu_tablet_config_descriptor,
  385 + sizeof(qemu_tablet_config_descriptor));
  386 + ret = sizeof(qemu_tablet_config_descriptor);
  387 + }
230 break; 388 break;
231 case USB_DT_STRING: 389 case USB_DT_STRING:
232 switch(value & 0xff) { 390 switch(value & 0xff) {
@@ -244,7 +402,10 @@ static int usb_mouse_handle_control(USBDevice *dev, int request, int value, @@ -244,7 +402,10 @@ static int usb_mouse_handle_control(USBDevice *dev, int request, int value,
244 break; 402 break;
245 case 2: 403 case 2:
246 /* product description */ 404 /* product description */
247 - ret = set_usb_string(data, "QEMU USB Mouse"); 405 + if (s->kind == USB_MOUSE)
  406 + ret = set_usb_string(data, "QEMU USB Mouse");
  407 + else if (s->kind == USB_TABLET)
  408 + ret = set_usb_string(data, "QEMU USB Tablet");
248 break; 409 break;
249 case 3: 410 case 3:
250 /* vendor description */ 411 /* vendor description */
@@ -282,16 +443,25 @@ static int usb_mouse_handle_control(USBDevice *dev, int request, int value, @@ -282,16 +443,25 @@ static int usb_mouse_handle_control(USBDevice *dev, int request, int value,
282 case InterfaceRequest | USB_REQ_GET_DESCRIPTOR: 443 case InterfaceRequest | USB_REQ_GET_DESCRIPTOR:
283 switch(value >> 8) { 444 switch(value >> 8) {
284 case 0x22: 445 case 0x22:
285 - memcpy(data, qemu_mouse_hid_report_descriptor,  
286 - sizeof(qemu_mouse_hid_report_descriptor));  
287 - ret = sizeof(qemu_mouse_hid_report_descriptor);  
288 - break; 446 + if (s->kind == USB_MOUSE) {
  447 + memcpy(data, qemu_mouse_hid_report_descriptor,
  448 + sizeof(qemu_mouse_hid_report_descriptor));
  449 + ret = sizeof(qemu_mouse_hid_report_descriptor);
  450 + } else if (s->kind == USB_TABLET) {
  451 + memcpy(data, qemu_tablet_hid_report_descriptor,
  452 + sizeof(qemu_tablet_hid_report_descriptor));
  453 + ret = sizeof(qemu_tablet_hid_report_descriptor);
  454 + }
  455 + break;
289 default: 456 default:
290 goto fail; 457 goto fail;
291 } 458 }
292 break; 459 break;
293 case GET_REPORT: 460 case GET_REPORT:
294 - ret = usb_mouse_poll(s, data, length); 461 + if (s->kind == USB_MOUSE)
  462 + ret = usb_mouse_poll(s, data, length);
  463 + else if (s->kind == USB_TABLET)
  464 + ret = usb_tablet_poll(s, data, length);
295 break; 465 break;
296 case SET_IDLE: 466 case SET_IDLE:
297 ret = 0; 467 ret = 0;
@@ -308,12 +478,15 @@ static int usb_mouse_handle_data(USBDevice *dev, int pid, @@ -308,12 +478,15 @@ static int usb_mouse_handle_data(USBDevice *dev, int pid,
308 uint8_t devep, uint8_t *data, int len) 478 uint8_t devep, uint8_t *data, int len)
309 { 479 {
310 USBMouseState *s = (USBMouseState *)dev; 480 USBMouseState *s = (USBMouseState *)dev;
311 - int ret; 481 + int ret = 0;
312 482
313 switch(pid) { 483 switch(pid) {
314 case USB_TOKEN_IN: 484 case USB_TOKEN_IN:
315 if (devep == 1) { 485 if (devep == 1) {
316 - ret = usb_mouse_poll(s, data, len); 486 + if (s->kind == USB_MOUSE)
  487 + ret = usb_mouse_poll(s, data, len);
  488 + else if (s->kind == USB_TABLET)
  489 + ret = usb_tablet_poll(s, data, len);
317 } else { 490 } else {
318 goto fail; 491 goto fail;
319 } 492 }
@@ -327,6 +500,24 @@ static int usb_mouse_handle_data(USBDevice *dev, int pid, @@ -327,6 +500,24 @@ static int usb_mouse_handle_data(USBDevice *dev, int pid,
327 return ret; 500 return ret;
328 } 501 }
329 502
  503 +USBDevice *usb_tablet_init(void)
  504 +{
  505 + USBMouseState *s;
  506 +
  507 + s = qemu_mallocz(sizeof(USBMouseState));
  508 + if (!s)
  509 + return NULL;
  510 + s->dev.speed = USB_SPEED_FULL;
  511 + s->dev.handle_packet = usb_generic_handle_packet;
  512 +
  513 + s->dev.handle_reset = usb_mouse_handle_reset;
  514 + s->dev.handle_control = usb_mouse_handle_control;
  515 + s->dev.handle_data = usb_mouse_handle_data;
  516 + s->kind = USB_TABLET;
  517 +
  518 + return (USBDevice *)s;
  519 +}
  520 +
330 USBDevice *usb_mouse_init(void) 521 USBDevice *usb_mouse_init(void)
331 { 522 {
332 USBMouseState *s; 523 USBMouseState *s;
@@ -340,8 +531,7 @@ USBDevice *usb_mouse_init(void) @@ -340,8 +531,7 @@ USBDevice *usb_mouse_init(void)
340 s->dev.handle_reset = usb_mouse_handle_reset; 531 s->dev.handle_reset = usb_mouse_handle_reset;
341 s->dev.handle_control = usb_mouse_handle_control; 532 s->dev.handle_control = usb_mouse_handle_control;
342 s->dev.handle_data = usb_mouse_handle_data; 533 s->dev.handle_data = usb_mouse_handle_data;
  534 + s->kind = USB_MOUSE;
343 535
344 - qemu_add_mouse_event_handler(usb_mouse_event, s);  
345 -  
346 return (USBDevice *)s; 536 return (USBDevice *)s;
347 } 537 }
hw/usb.h
@@ -163,3 +163,4 @@ void usb_host_info(void); @@ -163,3 +163,4 @@ void usb_host_info(void);
163 163
164 /* usb-hid.c */ 164 /* usb-hid.c */
165 USBDevice *usb_mouse_init(void); 165 USBDevice *usb_mouse_init(void);
  166 +USBDevice *usb_tablet_init(void);
@@ -39,6 +39,10 @@ static int gui_keysym; @@ -39,6 +39,10 @@ static int gui_keysym;
39 static int gui_fullscreen_initial_grab; 39 static int gui_fullscreen_initial_grab;
40 static int gui_grab_code = KMOD_LALT | KMOD_LCTRL; 40 static int gui_grab_code = KMOD_LALT | KMOD_LCTRL;
41 static uint8_t modifiers_state[256]; 41 static uint8_t modifiers_state[256];
  42 +static int width, height;
  43 +static SDL_Cursor *sdl_cursor_normal;
  44 +static SDL_Cursor *sdl_cursor_hidden;
  45 +static int absolute_enabled = 0;
42 46
43 static void sdl_update(DisplayState *ds, int x, int y, int w, int h) 47 static void sdl_update(DisplayState *ds, int x, int y, int w, int h)
44 { 48 {
@@ -56,6 +60,9 @@ static void sdl_resize(DisplayState *ds, int w, int h) @@ -56,6 +60,9 @@ static void sdl_resize(DisplayState *ds, int w, int h)
56 if (gui_fullscreen) 60 if (gui_fullscreen)
57 flags |= SDL_FULLSCREEN; 61 flags |= SDL_FULLSCREEN;
58 62
  63 + width = w;
  64 + height = h;
  65 +
59 again: 66 again:
60 screen = SDL_SetVideoMode(w, h, 0, flags); 67 screen = SDL_SetVideoMode(w, h, 0, flags);
61 if (!screen) { 68 if (!screen) {
@@ -271,9 +278,21 @@ static void sdl_update_caption(void) @@ -271,9 +278,21 @@ static void sdl_update_caption(void)
271 SDL_WM_SetCaption(buf, "QEMU"); 278 SDL_WM_SetCaption(buf, "QEMU");
272 } 279 }
273 280
  281 +static void sdl_hide_cursor(void)
  282 +{
  283 + SDL_SetCursor(sdl_cursor_hidden);
  284 +}
  285 +
  286 +static void sdl_show_cursor(void)
  287 +{
  288 + if (!kbd_mouse_is_absolute()) {
  289 + SDL_SetCursor(sdl_cursor_normal);
  290 + }
  291 +}
  292 +
274 static void sdl_grab_start(void) 293 static void sdl_grab_start(void)
275 { 294 {
276 - SDL_ShowCursor(0); 295 + sdl_hide_cursor();
277 SDL_WM_GrabInput(SDL_GRAB_ON); 296 SDL_WM_GrabInput(SDL_GRAB_ON);
278 /* dummy read to avoid moving the mouse */ 297 /* dummy read to avoid moving the mouse */
279 SDL_GetRelativeMouseState(NULL, NULL); 298 SDL_GetRelativeMouseState(NULL, NULL);
@@ -284,7 +303,7 @@ static void sdl_grab_start(void) @@ -284,7 +303,7 @@ static void sdl_grab_start(void)
284 static void sdl_grab_end(void) 303 static void sdl_grab_end(void)
285 { 304 {
286 SDL_WM_GrabInput(SDL_GRAB_OFF); 305 SDL_WM_GrabInput(SDL_GRAB_OFF);
287 - SDL_ShowCursor(1); 306 + sdl_show_cursor();
288 gui_grab = 0; 307 gui_grab = 0;
289 sdl_update_caption(); 308 sdl_update_caption();
290 } 309 }
@@ -300,6 +319,21 @@ static void sdl_send_mouse_event(int dz) @@ -300,6 +319,21 @@ static void sdl_send_mouse_event(int dz)
300 buttons |= MOUSE_EVENT_RBUTTON; 319 buttons |= MOUSE_EVENT_RBUTTON;
301 if (state & SDL_BUTTON(SDL_BUTTON_MIDDLE)) 320 if (state & SDL_BUTTON(SDL_BUTTON_MIDDLE))
302 buttons |= MOUSE_EVENT_MBUTTON; 321 buttons |= MOUSE_EVENT_MBUTTON;
  322 +
  323 + if (kbd_mouse_is_absolute()) {
  324 + if (!absolute_enabled) {
  325 + sdl_hide_cursor();
  326 + if (gui_grab) {
  327 + sdl_grab_end();
  328 + }
  329 + absolute_enabled = 1;
  330 + }
  331 +
  332 + SDL_GetMouseState(&dx, &dy);
  333 + dx = dx * 0x7FFF / width;
  334 + dy = dy * 0x7FFF / height;
  335 + }
  336 +
303 kbd_mouse_event(dx, dy, dz, buttons); 337 kbd_mouse_event(dx, dy, dz, buttons);
304 } 338 }
305 339
@@ -423,7 +457,7 @@ static void sdl_refresh(DisplayState *ds) @@ -423,7 +457,7 @@ static void sdl_refresh(DisplayState *ds)
423 qemu_system_shutdown_request(); 457 qemu_system_shutdown_request();
424 break; 458 break;
425 case SDL_MOUSEMOTION: 459 case SDL_MOUSEMOTION:
426 - if (gui_grab) { 460 + if (gui_grab || kbd_mouse_is_absolute()) {
427 sdl_send_mouse_event(0); 461 sdl_send_mouse_event(0);
428 } 462 }
429 break; 463 break;
@@ -431,7 +465,7 @@ static void sdl_refresh(DisplayState *ds) @@ -431,7 +465,7 @@ static void sdl_refresh(DisplayState *ds)
431 case SDL_MOUSEBUTTONUP: 465 case SDL_MOUSEBUTTONUP:
432 { 466 {
433 SDL_MouseButtonEvent *bev = &ev->button; 467 SDL_MouseButtonEvent *bev = &ev->button;
434 - if (!gui_grab) { 468 + if (!gui_grab && !kbd_mouse_is_absolute()) {
435 if (ev->type == SDL_MOUSEBUTTONDOWN && 469 if (ev->type == SDL_MOUSEBUTTONDOWN &&
436 (bev->state & SDL_BUTTON_LMASK)) { 470 (bev->state & SDL_BUTTON_LMASK)) {
437 /* start grabbing all events */ 471 /* start grabbing all events */
@@ -441,9 +475,9 @@ static void sdl_refresh(DisplayState *ds) @@ -441,9 +475,9 @@ static void sdl_refresh(DisplayState *ds)
441 int dz; 475 int dz;
442 dz = 0; 476 dz = 0;
443 #ifdef SDL_BUTTON_WHEELUP 477 #ifdef SDL_BUTTON_WHEELUP
444 - if (bev->button == SDL_BUTTON_WHEELUP) { 478 + if (bev->button == SDL_BUTTON_WHEELUP && ev->type == SDL_MOUSEBUTTONDOWN) {
445 dz = -1; 479 dz = -1;
446 - } else if (bev->button == SDL_BUTTON_WHEELDOWN) { 480 + } else if (bev->button == SDL_BUTTON_WHEELDOWN && ev->type == SDL_MOUSEBUTTONDOWN) {
447 dz = 1; 481 dz = 1;
448 } 482 }
449 #endif 483 #endif
@@ -471,6 +505,7 @@ static void sdl_cleanup(void) @@ -471,6 +505,7 @@ static void sdl_cleanup(void)
471 void sdl_display_init(DisplayState *ds, int full_screen) 505 void sdl_display_init(DisplayState *ds, int full_screen)
472 { 506 {
473 int flags; 507 int flags;
  508 + uint8_t data = 0;
474 509
475 #if defined(__APPLE__) 510 #if defined(__APPLE__)
476 /* always use generic keymaps */ 511 /* always use generic keymaps */
@@ -504,6 +539,9 @@ void sdl_display_init(DisplayState *ds, int full_screen) @@ -504,6 +539,9 @@ void sdl_display_init(DisplayState *ds, int full_screen)
504 SDL_EnableUNICODE(1); 539 SDL_EnableUNICODE(1);
505 gui_grab = 0; 540 gui_grab = 0;
506 541
  542 + sdl_cursor_hidden = SDL_CreateCursor(&data, &data, 8, 1, 0, 0);
  543 + sdl_cursor_normal = SDL_GetCursor();
  544 +
507 atexit(sdl_cleanup); 545 atexit(sdl_cleanup);
508 if (full_screen) { 546 if (full_screen) {
509 gui_fullscreen = 1; 547 gui_fullscreen = 1;
@@ -474,6 +474,7 @@ static QEMUPutKBDEvent *qemu_put_kbd_event; @@ -474,6 +474,7 @@ static QEMUPutKBDEvent *qemu_put_kbd_event;
474 static void *qemu_put_kbd_event_opaque; 474 static void *qemu_put_kbd_event_opaque;
475 static QEMUPutMouseEvent *qemu_put_mouse_event; 475 static QEMUPutMouseEvent *qemu_put_mouse_event;
476 static void *qemu_put_mouse_event_opaque; 476 static void *qemu_put_mouse_event_opaque;
  477 +static int qemu_put_mouse_event_absolute;
477 478
478 void qemu_add_kbd_event_handler(QEMUPutKBDEvent *func, void *opaque) 479 void qemu_add_kbd_event_handler(QEMUPutKBDEvent *func, void *opaque)
479 { 480 {
@@ -481,10 +482,11 @@ void qemu_add_kbd_event_handler(QEMUPutKBDEvent *func, void *opaque) @@ -481,10 +482,11 @@ void qemu_add_kbd_event_handler(QEMUPutKBDEvent *func, void *opaque)
481 qemu_put_kbd_event = func; 482 qemu_put_kbd_event = func;
482 } 483 }
483 484
484 -void qemu_add_mouse_event_handler(QEMUPutMouseEvent *func, void *opaque) 485 +void qemu_add_mouse_event_handler(QEMUPutMouseEvent *func, void *opaque, int absolute)
485 { 486 {
486 qemu_put_mouse_event_opaque = opaque; 487 qemu_put_mouse_event_opaque = opaque;
487 qemu_put_mouse_event = func; 488 qemu_put_mouse_event = func;
  489 + qemu_put_mouse_event_absolute = absolute;
488 } 490 }
489 491
490 void kbd_put_keycode(int keycode) 492 void kbd_put_keycode(int keycode)
@@ -502,6 +504,11 @@ void kbd_mouse_event(int dx, int dy, int dz, int buttons_state) @@ -502,6 +504,11 @@ void kbd_mouse_event(int dx, int dy, int dz, int buttons_state)
502 } 504 }
503 } 505 }
504 506
  507 +int kbd_mouse_is_absolute(void)
  508 +{
  509 + return qemu_put_mouse_event_absolute;
  510 +}
  511 +
505 /***********************************************************/ 512 /***********************************************************/
506 /* timers */ 513 /* timers */
507 514
@@ -3242,6 +3249,10 @@ static int usb_device_add(const char *devname) @@ -3242,6 +3249,10 @@ static int usb_device_add(const char *devname)
3242 dev = usb_mouse_init(); 3249 dev = usb_mouse_init();
3243 if (!dev) 3250 if (!dev)
3244 return -1; 3251 return -1;
  3252 + } else if (!strcmp(devname, "tablet")) {
  3253 + dev = usb_tablet_init();
  3254 + if (!dev)
  3255 + return -1;
3245 } else { 3256 } else {
3246 return -1; 3257 return -1;
3247 } 3258 }
@@ -158,10 +158,11 @@ typedef void QEMUPutKBDEvent(void *opaque, int keycode); @@ -158,10 +158,11 @@ typedef void QEMUPutKBDEvent(void *opaque, int keycode);
158 typedef void QEMUPutMouseEvent(void *opaque, int dx, int dy, int dz, int buttons_state); 158 typedef void QEMUPutMouseEvent(void *opaque, int dx, int dy, int dz, int buttons_state);
159 159
160 void qemu_add_kbd_event_handler(QEMUPutKBDEvent *func, void *opaque); 160 void qemu_add_kbd_event_handler(QEMUPutKBDEvent *func, void *opaque);
161 -void qemu_add_mouse_event_handler(QEMUPutMouseEvent *func, void *opaque); 161 +void qemu_add_mouse_event_handler(QEMUPutMouseEvent *func, void *opaque, int absolute);
162 162
163 void kbd_put_keycode(int keycode); 163 void kbd_put_keycode(int keycode);
164 void kbd_mouse_event(int dx, int dy, int dz, int buttons_state); 164 void kbd_mouse_event(int dx, int dy, int dz, int buttons_state);
  165 +int kbd_mouse_is_absolute(void);
165 166
166 /* keysym is a unicode code except for special keys (see QEMU_KEY_xxx 167 /* keysym is a unicode code except for special keys (see QEMU_KEY_xxx
167 constants) */ 168 constants) */