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 560 s->common.update_arg = update_arg;
561 561 ps2_reset(&s->common);
562 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 564 qemu_register_reset(ps2_reset, &s->common);
565 565 return s;
566 566 }
... ...
hw/usb-hid.c
... ... @@ -30,9 +30,15 @@
30 30 #define SET_IDLE 0x210a
31 31 #define SET_PROTOCOL 0x210b
32 32  
  33 +#define USB_MOUSE 1
  34 +#define USB_TABLET 2
  35 +
33 36 typedef struct USBMouseState {
34 37 USBDevice dev;
35 38 int dx, dy, dz, buttons_state;
  39 + int x, y;
  40 + int kind;
  41 + int mouse_grabbed;
36 42 } USBMouseState;
37 43  
38 44 /* mostly the same values as the Bochs USB Mouse device */
... ... @@ -93,6 +99,15 @@ static const uint8_t qemu_mouse_config_descriptor[] = {
93 99 0x02, /* u8 if_bInterfaceProtocol; [usb1.1 or single tt] */
94 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 111 /* one endpoint (status change endpoint) */
97 112 0x07, /* u8 ep_bLength; */
98 113 0x05, /* u8 ep_bDescriptorType; Endpoint */
... ... @@ -100,6 +115,44 @@ static const uint8_t qemu_mouse_config_descriptor[] = {
100 115 0x03, /* u8 ep_bmAttributes; Interrupt */
101 116 0x03, 0x00, /* u16 ep_wMaxPacketSize; */
102 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 157 /* HID descriptor */
105 158 0x09, /* u8 bLength; */
... ... @@ -108,7 +161,15 @@ static const uint8_t qemu_mouse_config_descriptor[] = {
108 161 0x00, /* u8 country_code */
109 162 0x01, /* u8 num_descriptors */
110 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 175 static const uint8_t qemu_mouse_hid_report_descriptor[] = {
... ... @@ -121,6 +182,46 @@ static const uint8_t qemu_mouse_hid_report_descriptor[] = {
121 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 225 static void usb_mouse_event(void *opaque,
125 226 int dx1, int dy1, int dz1, int buttons_state)
126 227 {
... ... @@ -132,6 +233,17 @@ static void usb_mouse_event(void *opaque,
132 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 247 static inline int int_clamp(int val, int vmin, int vmax)
136 248 {
137 249 if (val < vmin)
... ... @@ -146,6 +258,11 @@ static int usb_mouse_poll(USBMouseState *s, uint8_t *buf, int len)
146 258 {
147 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 266 dx = int_clamp(s->dx, -128, 127);
150 267 dy = int_clamp(s->dy, -128, 127);
151 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 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 326 static void usb_mouse_handle_reset(USBDevice *dev)
177 327 {
178 328 USBMouseState *s = (USBMouseState *)dev;
... ... @@ -180,6 +330,8 @@ static void usb_mouse_handle_reset(USBDevice *dev)
180 330 s->dx = 0;
181 331 s->dy = 0;
182 332 s->dz = 0;
  333 + s->x = 0;
  334 + s->y = 0;
183 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 339 int index, int length, uint8_t *data)
188 340 {
189 341 USBMouseState *s = (USBMouseState *)dev;
190   - int ret;
  342 + int ret = 0;
191 343  
192 344 switch(request) {
193 345 case DeviceRequest | USB_REQ_GET_STATUS:
... ... @@ -224,9 +376,15 @@ static int usb_mouse_handle_control(USBDevice *dev, int request, int value,
224 376 ret = sizeof(qemu_mouse_dev_descriptor);
225 377 break;
226 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 388 break;
231 389 case USB_DT_STRING:
232 390 switch(value & 0xff) {
... ... @@ -244,7 +402,10 @@ static int usb_mouse_handle_control(USBDevice *dev, int request, int value,
244 402 break;
245 403 case 2:
246 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 409 break;
249 410 case 3:
250 411 /* vendor description */
... ... @@ -282,16 +443,25 @@ static int usb_mouse_handle_control(USBDevice *dev, int request, int value,
282 443 case InterfaceRequest | USB_REQ_GET_DESCRIPTOR:
283 444 switch(value >> 8) {
284 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 456 default:
290 457 goto fail;
291 458 }
292 459 break;
293 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 465 break;
296 466 case SET_IDLE:
297 467 ret = 0;
... ... @@ -308,12 +478,15 @@ static int usb_mouse_handle_data(USBDevice *dev, int pid,
308 478 uint8_t devep, uint8_t *data, int len)
309 479 {
310 480 USBMouseState *s = (USBMouseState *)dev;
311   - int ret;
  481 + int ret = 0;
312 482  
313 483 switch(pid) {
314 484 case USB_TOKEN_IN:
315 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 490 } else {
318 491 goto fail;
319 492 }
... ... @@ -327,6 +500,24 @@ static int usb_mouse_handle_data(USBDevice *dev, int pid,
327 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 521 USBDevice *usb_mouse_init(void)
331 522 {
332 523 USBMouseState *s;
... ... @@ -340,8 +531,7 @@ USBDevice *usb_mouse_init(void)
340 531 s->dev.handle_reset = usb_mouse_handle_reset;
341 532 s->dev.handle_control = usb_mouse_handle_control;
342 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 536 return (USBDevice *)s;
347 537 }
... ...
hw/usb.h
... ... @@ -163,3 +163,4 @@ void usb_host_info(void);
163 163  
164 164 /* usb-hid.c */
165 165 USBDevice *usb_mouse_init(void);
  166 +USBDevice *usb_tablet_init(void);
... ...
... ... @@ -39,6 +39,10 @@ static int gui_keysym;
39 39 static int gui_fullscreen_initial_grab;
40 40 static int gui_grab_code = KMOD_LALT | KMOD_LCTRL;
41 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 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 60 if (gui_fullscreen)
57 61 flags |= SDL_FULLSCREEN;
58 62  
  63 + width = w;
  64 + height = h;
  65 +
59 66 again:
60 67 screen = SDL_SetVideoMode(w, h, 0, flags);
61 68 if (!screen) {
... ... @@ -271,9 +278,21 @@ static void sdl_update_caption(void)
271 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 293 static void sdl_grab_start(void)
275 294 {
276   - SDL_ShowCursor(0);
  295 + sdl_hide_cursor();
277 296 SDL_WM_GrabInput(SDL_GRAB_ON);
278 297 /* dummy read to avoid moving the mouse */
279 298 SDL_GetRelativeMouseState(NULL, NULL);
... ... @@ -284,7 +303,7 @@ static void sdl_grab_start(void)
284 303 static void sdl_grab_end(void)
285 304 {
286 305 SDL_WM_GrabInput(SDL_GRAB_OFF);
287   - SDL_ShowCursor(1);
  306 + sdl_show_cursor();
288 307 gui_grab = 0;
289 308 sdl_update_caption();
290 309 }
... ... @@ -300,6 +319,21 @@ static void sdl_send_mouse_event(int dz)
300 319 buttons |= MOUSE_EVENT_RBUTTON;
301 320 if (state & SDL_BUTTON(SDL_BUTTON_MIDDLE))
302 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 337 kbd_mouse_event(dx, dy, dz, buttons);
304 338 }
305 339  
... ... @@ -423,7 +457,7 @@ static void sdl_refresh(DisplayState *ds)
423 457 qemu_system_shutdown_request();
424 458 break;
425 459 case SDL_MOUSEMOTION:
426   - if (gui_grab) {
  460 + if (gui_grab || kbd_mouse_is_absolute()) {
427 461 sdl_send_mouse_event(0);
428 462 }
429 463 break;
... ... @@ -431,7 +465,7 @@ static void sdl_refresh(DisplayState *ds)
431 465 case SDL_MOUSEBUTTONUP:
432 466 {
433 467 SDL_MouseButtonEvent *bev = &ev->button;
434   - if (!gui_grab) {
  468 + if (!gui_grab && !kbd_mouse_is_absolute()) {
435 469 if (ev->type == SDL_MOUSEBUTTONDOWN &&
436 470 (bev->state & SDL_BUTTON_LMASK)) {
437 471 /* start grabbing all events */
... ... @@ -441,9 +475,9 @@ static void sdl_refresh(DisplayState *ds)
441 475 int dz;
442 476 dz = 0;
443 477 #ifdef SDL_BUTTON_WHEELUP
444   - if (bev->button == SDL_BUTTON_WHEELUP) {
  478 + if (bev->button == SDL_BUTTON_WHEELUP && ev->type == SDL_MOUSEBUTTONDOWN) {
445 479 dz = -1;
446   - } else if (bev->button == SDL_BUTTON_WHEELDOWN) {
  480 + } else if (bev->button == SDL_BUTTON_WHEELDOWN && ev->type == SDL_MOUSEBUTTONDOWN) {
447 481 dz = 1;
448 482 }
449 483 #endif
... ... @@ -471,6 +505,7 @@ static void sdl_cleanup(void)
471 505 void sdl_display_init(DisplayState *ds, int full_screen)
472 506 {
473 507 int flags;
  508 + uint8_t data = 0;
474 509  
475 510 #if defined(__APPLE__)
476 511 /* always use generic keymaps */
... ... @@ -504,6 +539,9 @@ void sdl_display_init(DisplayState *ds, int full_screen)
504 539 SDL_EnableUNICODE(1);
505 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 545 atexit(sdl_cleanup);
508 546 if (full_screen) {
509 547 gui_fullscreen = 1;
... ...
... ... @@ -474,6 +474,7 @@ static QEMUPutKBDEvent *qemu_put_kbd_event;
474 474 static void *qemu_put_kbd_event_opaque;
475 475 static QEMUPutMouseEvent *qemu_put_mouse_event;
476 476 static void *qemu_put_mouse_event_opaque;
  477 +static int qemu_put_mouse_event_absolute;
477 478  
478 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 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 487 qemu_put_mouse_event_opaque = opaque;
487 488 qemu_put_mouse_event = func;
  489 + qemu_put_mouse_event_absolute = absolute;
488 490 }
489 491  
490 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 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 513 /* timers */
507 514  
... ... @@ -3242,6 +3249,10 @@ static int usb_device_add(const char *devname)
3242 3249 dev = usb_mouse_init();
3243 3250 if (!dev)
3244 3251 return -1;
  3252 + } else if (!strcmp(devname, "tablet")) {
  3253 + dev = usb_tablet_init();
  3254 + if (!dev)
  3255 + return -1;
3245 3256 } else {
3246 3257 return -1;
3247 3258 }
... ...
... ... @@ -158,10 +158,11 @@ typedef void QEMUPutKBDEvent(void *opaque, int keycode);
158 158 typedef void QEMUPutMouseEvent(void *opaque, int dx, int dy, int dz, int buttons_state);
159 159  
160 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 163 void kbd_put_keycode(int keycode);
164 164 void kbd_mouse_event(int dx, int dy, int dz, int buttons_state);
  165 +int kbd_mouse_is_absolute(void);
165 166  
166 167 /* keysym is a unicode code except for special keys (see QEMU_KEY_xxx
167 168 constants) */
... ...