Commit 09b26c5ec06ff7531a2a2a7b1146011c87285f81
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
Showing
6 changed files
with
265 additions
and
24 deletions
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
sdl.c
@@ -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; |
vl.c
@@ -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 | } |
vl.h
@@ -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) */ |