Changeset 47571 in vbox for trunk/src/VBox
- Timestamp:
- Aug 7, 2013 9:49:33 AM (12 years ago)
- svn:sync-xref-src-repo-rev:
- 87771
- Location:
- trunk/src/VBox
- Files:
-
- 10 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Devices/Input/DevPS2.cpp
r47259 r47571 1391 1391 1392 1392 /** 1393 * @interface_method_impl{PDMIMOUSEPORT, pfnPutEventM T}1394 */ 1395 static DECLCALLBACK(int) kbdMousePutEventM T(PPDMIMOUSEPORT pInterface,1396 uint32_t x, uint32_t y,1397 uint32_t cContact,1398 uint32_t fContact)1393 * @interface_method_impl{PDMIMOUSEPORT, pfnPutEventMultiTouch} 1394 */ 1395 static DECLCALLBACK(int) kbdMousePutEventMultiTouch(PPDMIMOUSEPORT pInterface, 1396 uint8_t cContacts, 1397 const uint64_t *pau64Contacts, 1398 uint32_t u32ScanTime) 1399 1399 { 1400 1400 AssertFailedReturn(VERR_NOT_SUPPORTED); 1401 NOREF(pInterface); NOREF( x); NOREF(y); NOREF(cContact); NOREF(fContact);1401 NOREF(pInterface); NOREF(cContacts); NOREF(pau64Contacts); NOREF(u32ScanTime); 1402 1402 } 1403 1403 … … 1568 1568 pThis->Mouse.IPort.pfnPutEvent = kbdMousePutEvent; 1569 1569 pThis->Mouse.IPort.pfnPutEventAbs = kbdMousePutEventAbs; 1570 pThis->Mouse.IPort.pfnPutEventM T = kbdMousePutEventMT;1570 pThis->Mouse.IPort.pfnPutEventMultiTouch = kbdMousePutEventMultiTouch; 1571 1571 1572 1572 /* -
trunk/src/VBox/Devices/Input/DrvMouseQueue.cpp
r47360 r47571 61 61 * Event type for @a DRVMOUSEQUEUEITEM 62 62 */ 63 enum EVENTTYPE { RELATIVE, ABSOLUTE , MULTITOUCH};63 enum EVENTTYPE { RELATIVE, ABSOLUTE }; 64 64 65 65 /** … … 90 90 int32_t dw; 91 91 } Absolute; 92 struct93 {94 uint32_t fContact;95 uint32_t x;96 uint32_t y;97 uint32_t cContact;98 } MultiTouch;99 92 } u; 100 93 } DRVMOUSEQUEUEITEM, *PDRVMOUSEQUEUEITEM; … … 181 174 182 175 183 /** 184 * @interface_method_impl{PDMIMOUSEPORT,pfnPutEventMT} 185 */ 186 static DECLCALLBACK(int) drvMouseQueuePutEventMT(PPDMIMOUSEPORT pInterface, 187 uint32_t x, uint32_t y, 188 uint32_t cContact, 189 uint32_t fContact) 190 { 191 PDRVMOUSEQUEUE pDrv = IMOUSEPORT_2_DRVMOUSEQUEUE(pInterface); 192 if (pDrv->fInactive) 193 return VINF_SUCCESS; 194 195 PDRVMOUSEQUEUEITEM pItem = (PDRVMOUSEQUEUEITEM)PDMQueueAlloc(pDrv->pQueue); 196 if (pItem) 197 { 198 RT_ZERO(pItem->u.padding); 199 pItem->enmType = MULTITOUCH; 200 pItem->u.MultiTouch.x = x; 201 pItem->u.MultiTouch.y = y; 202 pItem->u.MultiTouch.cContact = cContact; 203 pItem->u.MultiTouch.fContact = fContact; 204 PDMQueueInsert(pDrv->pQueue, &pItem->Core); 205 return VINF_SUCCESS; 206 } 207 return VERR_PDM_NO_QUEUE_ITEMS; 208 } 209 176 static DECLCALLBACK(int) drvMouseQueuePutEventMultiTouch(PPDMIMOUSEPORT pInterface, 177 uint8_t cContacts, 178 const uint64_t *pau64Contacts, 179 uint32_t u32ScanTime) 180 { 181 PDRVMOUSEQUEUE pThis = IMOUSEPORT_2_DRVMOUSEQUEUE(pInterface); 182 return pThis->pUpPort->pfnPutEventMultiTouch(pThis->pUpPort, cContacts, pau64Contacts, u32ScanTime); 183 } 210 184 211 185 /* -=-=-=-=- IConnector -=-=-=-=- */ … … 260 234 pItem->u.Absolute.dw, 261 235 pItem->u.Absolute.fButtons); 262 else if (pItem->enmType == MULTITOUCH)263 rc = pThis->pUpPort->pfnPutEventMT(pThis->pUpPort,264 pItem->u.MultiTouch.x,265 pItem->u.MultiTouch.y,266 pItem->u.MultiTouch.cContact,267 pItem->u.MultiTouch.fContact);268 236 else 269 237 return false; … … 366 334 pDrv->IPort.pfnPutEvent = drvMouseQueuePutEvent; 367 335 pDrv->IPort.pfnPutEventAbs = drvMouseQueuePutEventAbs; 368 pDrv->IPort.pfnPutEventM T = drvMouseQueuePutEventMT;336 pDrv->IPort.pfnPutEventMultiTouch = drvMouseQueuePutEventMultiTouch; 369 337 370 338 /* -
trunk/src/VBox/Devices/Input/UsbMouse.cpp
r47468 r47571 139 139 uint32_t fButtons; 140 140 } Absolute; 141 struct142 {143 uint32_t fContact;144 uint32_t x;145 uint32_t y;146 uint32_t cContact;147 } MultiTouch;148 141 } u; 149 142 } USBHIDM_ACCUM, *PUSBHIDM_ACCUM; 143 144 #define MT_CONTACTS_PER_REPORT 5 145 146 #define MT_CONTACT_MAX_COUNT 10 147 148 #define MT_CONTACT_F_IN_CONTACT 0x01 149 #define MT_CONTACT_F_IN_RANGE 0x02 150 151 #define MT_CONTACT_S_ACTIVE 0x01 /* Contact must be reported to the guest. */ 152 #define MT_CONTACT_S_CANCELLED 0x02 /* Contact loss must be reported to the guest. */ 153 #define MT_CONTACT_S_REUSED 0x04 /* Report contact loss for the oldId and then new contact for the id. */ 154 #define MT_CONTACT_S_DIRTY 0x08 /* Temporary flag used to track already processed elements. */ 155 156 typedef struct MTCONTACT 157 { 158 uint16_t x; 159 uint16_t y; 160 uint8_t id; 161 uint8_t flags; 162 uint8_t status; 163 uint8_t oldId; /* Valid only if MT_CONTACT_S_REUSED is set. */ 164 } MTCONTACT; 150 165 151 166 … … 211 226 } Lun0; 212 227 228 MTCONTACT aCurrentContactState[MT_CONTACT_MAX_COUNT]; 229 MTCONTACT aReportingContactState[MT_CONTACT_MAX_COUNT]; 230 uint32_t u32LastTouchScanTime; 231 bool fTouchReporting; 213 232 } USBHID; 214 233 /** Pointer to the USB HID instance data. */ 215 234 typedef USBHID *PUSBHID; 216 235 236 #pragma pack(1) 217 237 /** 218 238 * The USB HID report structure for relative device. … … 238 258 239 259 /** 240 * The USB HID report structure for the multi-touch device. 241 */ 242 243 typedef struct USBHIDMT_REPORT 244 { 245 uint8_t idReport; 246 uint8_t fContact; 247 uint16_t x; 248 uint16_t y; 249 uint8_t cContact; 250 } USBHIDMT_REPORT, *PUSBHIDMT_REPORT; 251 252 /** 253 * The combined USB HID report union for relative, absolute and multi-touch 260 * The combined USB HID report union for relative and absolute 254 261 * devices. 255 262 */ … … 258 265 USBHIDM_REPORT m; 259 266 USBHIDT_REPORT t; 260 USBHIDMT_REPORT mt;261 267 } USBHIDTM_REPORT, *PUSBHIDTM_REPORT; 268 269 /** 270 * The USB HID report structure for the multi-touch device. 271 */ 272 typedef struct USBHIDMT_REPORT 273 { 274 uint8_t idReport; 275 uint8_t cContacts; 276 struct 277 { 278 uint8_t fContact; 279 uint8_t cContact; 280 uint16_t x; 281 uint16_t y; 282 } aContacts[MT_CONTACTS_PER_REPORT]; 283 uint32_t u32ScanTime; 284 } USBHIDMT_REPORT, *PUSBHIDMT_REPORT; 285 #pragma pack() 262 286 263 287 /******************************************************************************* … … 303 327 /* .bmAttributes = */ 3 /* interrupt */, 304 328 /* .wMaxPacketSize = */ 6, 329 /* .bInterval = */ 10, 330 }, 331 /* .pvMore = */ NULL, 332 /* .pvClass = */ NULL, 333 /* .cbClass = */ 0 334 }, 335 }; 336 337 static const VUSBDESCENDPOINTEX g_aUsbHidMTEndpointDescs[] = 338 { 339 { 340 { 341 /* .bLength = */ sizeof(VUSBDESCENDPOINT), 342 /* .bDescriptorType = */ VUSB_DT_ENDPOINT, 343 /* .bEndpointAddress = */ 0x81 /* ep=1, in */, 344 /* .bmAttributes = */ 3 /* interrupt */, 345 /* .wMaxPacketSize = */ 64, 305 346 /* .bInterval = */ 10, 306 347 }, … … 384 425 }; 385 426 427 /* 428 * Multi-touch device implementation based on "Windows Pointer Device Data Delivery Protocol" 429 * specification. 430 */ 431 432 #define REPORTID_TOUCH_POINTER 1 433 #define REPORTID_TOUCH_EVENT 2 434 #define REPORTID_TOUCH_MAX_COUNT 3 435 #define REPORTID_TOUCH_QABLOB 4 436 #define REPORTID_TOUCH_DEVCONFIG 5 437 386 438 static const uint8_t g_UsbHidMTReportDesc[] = 387 439 { 388 /* Usage Page */ 0x05, 0x0D, /* Digitisers */ 389 /* Usage */ 0x09, 0x04, /* Touch Screen */ 390 /* Collection */ 0xA1, 0x01, /* Application */ 391 /* Report ID */ 0x85, REPORTID_MOUSE, 392 /* Usage */ 0x09, 0x22, /* Finger */ 393 /* Collection */ 0xA1, 0x00, /* Physical */ 394 /* Usage */ 0x09, 0x42, /* Tip Switch */ 395 /* Usage */ 0x09, 0x32, /* In Range */ 396 /* Logical Minimum */ 0x15, 0x00, /* 0 */ 397 /* Logical Maximum */ 0x25, 0x01, /* 1 */ 398 /* Report Count */ 0x95, 0x02, /* 2 */ 399 /* Report Size */ 0x75, 0x01, /* 1 */ 400 /* Input */ 0x81, 0x02, /* Data, Value, Absolute, Bit field */ 401 /* Report Count */ 0x95, 0x06, /* 6 (padding bits) */ 402 /* Input */ 0x81, 0x03, /* Constant, Value, Absolute, Bit field */ 403 /* Usage Page */ 0x05, 0x01, /* Generic Desktop */ 404 /* Usage */ 0x09, 0x30, /* X */ 405 /* Usage */ 0x09, 0x31, /* Y */ 406 /* Logical Minimum */ 0x15, 0x00, /* 0 */ 407 /* Logical Maximum */ 0x26, 0xFF,0x7F,/* 0x7fff */ 408 /* Physical Minimum */ 0x35, 0x00, /* 0 */ 409 /* Physical Maximum */ 0x46, 0xFF,0x7F,/* 0x7fff */ 410 /* Report Size */ 0x75, 0x10, /* 16 */ 411 /* Report Count */ 0x95, 0x02, /* 2 */ 412 /* Input */ 0x81, 0x02, /* Data, Value, Absolute, Bit field */ 413 /* Usage Page */ 0x05, 0x0D, /* Digitisers */ 414 /* Usage */ 0x09, 0x51, /* Contact Identifier */ 415 /* Report Count */ 0x95, 0x01, /* 1 */ 416 /* Report Size */ 0x75, 0x08, /* 8 */ 417 /* Input */ 0x81, 0x02, /* Data, Value, Absolute, Bit field */ 418 /* End Collection */ 0xC0, 419 /* Report ID */ 0x85, REPORTID_MAX_COUNT, 420 /* Usage */ 0x09, 0x55, /* Contact Count Maximum */ 421 /* Report Count */ 0x95, 0x01, /* 1 */ 422 /* Logical Maximum */ 0x25, 0x40, /* 64 */ 423 /* Feature */ 0xB1, 0x03, /* Constant, Value, Absolute, Bit field */ 424 /* End Collection */ 0xC0 440 /* Usage Page (Digitizer) */ 0x05, 0x0D, 441 /* Usage (Touch Screen) */ 0x09, 0x04, 442 /* Collection (Application) */ 0xA1, 0x01, 443 /* Report ID */ 0x85, REPORTID_TOUCH_EVENT, 444 /* Usage Page (Digitizer) */ 0x05, 0x0D, 445 /* Usage (Contact count) */ 0x09, 0x54, 446 /* Report Size (8) */ 0x75, 0x08, 447 /* Logical Minimum (0) */ 0x15, 0x00, 448 /* Logical Maximum (12) */ 0x25, 0x0C, 449 /* Report Count (1) */ 0x95, 0x01, 450 /* Input (Var) */ 0x81, 0x02, 451 452 /* MT_CONTACTS_PER_REPORT structs u8TipSwitch, u8ContactIdentifier, u16X, u16Y */ 453 /* 1 of 5 */ 454 /* Usage (Finger) */ 0x09, 0x22, 455 /* Collection (Logical) */ 0xA1, 0x02, 456 /* Usage (Tip Switch) */ 0x09, 0x42, 457 /* Logical Minimum (0) */ 0x15, 0x00, 458 /* Logical Maximum (1) */ 0x25, 0x01, 459 /* Report Size (1) */ 0x75, 0x01, 460 /* Report Count (1) */ 0x95, 0x01, 461 /* Input (Var) */ 0x81, 0x02, 462 463 /* Usage (In Range) */ 0x09, 0x32, 464 /* Logical Minimum (0) */ 0x15, 0x00, 465 /* Logical Maximum (1) */ 0x25, 0x01, 466 /* Report Size (1) */ 0x75, 0x01, 467 /* Report Count (1) */ 0x95, 0x01, 468 /* Input (Var) */ 0x81, 0x02, 469 470 /* Report Count (6) */ 0x95, 0x06, 471 /* Input (Cnst,Var) */ 0x81, 0x03, 472 473 /* Report Size (8) */ 0x75, 0x08, 474 /* Usage (Contact identifier) */ 0x09, 0x51, 475 /* Report Count (1) */ 0x95, 0x01, 476 /* Logical Minimum (0) */ 0x15, 0x00, 477 /* Logical Maximum (32) */ 0x25, 0x20, 478 /* Input (Var) */ 0x81, 0x02, 479 480 /* Usage Page (Generic Desktop) */ 0x05, 0x01, 481 /* Logical Maximum (32K) */ 0x26, 0xFF, 0x7F, 482 /* Report Size (16) */ 0x75, 0x10, 483 /* Usage (X) */ 0x09, 0x30, 484 /* Input (Var) */ 0x81, 0x02, 485 486 /* Usage (Y) */ 0x09, 0x31, 487 /* Input (Var) */ 0x81, 0x02, 488 /* End Collection */ 0xC0, 489 /* 2 of 5 */ 490 /* Usage Page (Digitizer) */ 0x05, 0x0D, 491 /* Usage (Finger) */ 0x09, 0x22, 492 /* Collection (Logical) */ 0xA1, 0x02, 493 /* Usage (Tip Switch) */ 0x09, 0x42, 494 /* Logical Minimum (0) */ 0x15, 0x00, 495 /* Logical Maximum (1) */ 0x25, 0x01, 496 /* Report Size (1) */ 0x75, 0x01, 497 /* Report Count (1) */ 0x95, 0x01, 498 /* Input (Var) */ 0x81, 0x02, 499 /* Usage (In Range) */ 0x09, 0x32, 500 /* Logical Minimum (0) */ 0x15, 0x00, 501 /* Logical Maximum (1) */ 0x25, 0x01, 502 /* Report Size (1) */ 0x75, 0x01, 503 /* Report Count (1) */ 0x95, 0x01, 504 /* Input (Var) */ 0x81, 0x02, 505 /* Report Count (6) */ 0x95, 0x06, 506 /* Input (Cnst,Var) */ 0x81, 0x03, 507 /* Report Size (8) */ 0x75, 0x08, 508 /* Usage (Contact identifier) */ 0x09, 0x51, 509 /* Report Count (1) */ 0x95, 0x01, 510 /* Logical Minimum (0) */ 0x15, 0x00, 511 /* Logical Maximum (32) */ 0x25, 0x20, 512 /* Input (Var) */ 0x81, 0x02, 513 /* Usage Page (Generic Desktop) */ 0x05, 0x01, 514 /* Logical Maximum (32K) */ 0x26, 0xFF, 0x7F, 515 /* Report Size (16) */ 0x75, 0x10, 516 /* Usage (X) */ 0x09, 0x30, 517 /* Input (Var) */ 0x81, 0x02, 518 /* Usage (Y) */ 0x09, 0x31, 519 /* Input (Var) */ 0x81, 0x02, 520 /* End Collection */ 0xC0, 521 /* 3 of 5 */ 522 /* Usage Page (Digitizer) */ 0x05, 0x0D, 523 /* Usage (Finger) */ 0x09, 0x22, 524 /* Collection (Logical) */ 0xA1, 0x02, 525 /* Usage (Tip Switch) */ 0x09, 0x42, 526 /* Logical Minimum (0) */ 0x15, 0x00, 527 /* Logical Maximum (1) */ 0x25, 0x01, 528 /* Report Size (1) */ 0x75, 0x01, 529 /* Report Count (1) */ 0x95, 0x01, 530 /* Input (Var) */ 0x81, 0x02, 531 /* Usage (In Range) */ 0x09, 0x32, 532 /* Logical Minimum (0) */ 0x15, 0x00, 533 /* Logical Maximum (1) */ 0x25, 0x01, 534 /* Report Size (1) */ 0x75, 0x01, 535 /* Report Count (1) */ 0x95, 0x01, 536 /* Input (Var) */ 0x81, 0x02, 537 /* Report Count (6) */ 0x95, 0x06, 538 /* Input (Cnst,Var) */ 0x81, 0x03, 539 /* Report Size (8) */ 0x75, 0x08, 540 /* Usage (Contact identifier) */ 0x09, 0x51, 541 /* Report Count (1) */ 0x95, 0x01, 542 /* Logical Minimum (0) */ 0x15, 0x00, 543 /* Logical Maximum (32) */ 0x25, 0x20, 544 /* Input (Var) */ 0x81, 0x02, 545 /* Usage Page (Generic Desktop) */ 0x05, 0x01, 546 /* Logical Maximum (32K) */ 0x26, 0xFF, 0x7F, 547 /* Report Size (16) */ 0x75, 0x10, 548 /* Usage (X) */ 0x09, 0x30, 549 /* Input (Var) */ 0x81, 0x02, 550 /* Usage (Y) */ 0x09, 0x31, 551 /* Input (Var) */ 0x81, 0x02, 552 /* End Collection */ 0xC0, 553 /* 4 of 5 */ 554 /* Usage Page (Digitizer) */ 0x05, 0x0D, 555 /* Usage (Finger) */ 0x09, 0x22, 556 /* Collection (Logical) */ 0xA1, 0x02, 557 /* Usage (Tip Switch) */ 0x09, 0x42, 558 /* Logical Minimum (0) */ 0x15, 0x00, 559 /* Logical Maximum (1) */ 0x25, 0x01, 560 /* Report Size (1) */ 0x75, 0x01, 561 /* Report Count (1) */ 0x95, 0x01, 562 /* Input (Var) */ 0x81, 0x02, 563 /* Usage (In Range) */ 0x09, 0x32, 564 /* Logical Minimum (0) */ 0x15, 0x00, 565 /* Logical Maximum (1) */ 0x25, 0x01, 566 /* Report Size (1) */ 0x75, 0x01, 567 /* Report Count (1) */ 0x95, 0x01, 568 /* Input (Var) */ 0x81, 0x02, 569 /* Report Count (6) */ 0x95, 0x06, 570 /* Input (Cnst,Var) */ 0x81, 0x03, 571 /* Report Size (8) */ 0x75, 0x08, 572 /* Usage (Contact identifier) */ 0x09, 0x51, 573 /* Report Count (1) */ 0x95, 0x01, 574 /* Logical Minimum (0) */ 0x15, 0x00, 575 /* Logical Maximum (32) */ 0x25, 0x20, 576 /* Input (Var) */ 0x81, 0x02, 577 /* Usage Page (Generic Desktop) */ 0x05, 0x01, 578 /* Logical Maximum (32K) */ 0x26, 0xFF, 0x7F, 579 /* Report Size (16) */ 0x75, 0x10, 580 /* Usage (X) */ 0x09, 0x30, 581 /* Input (Var) */ 0x81, 0x02, 582 /* Usage (Y) */ 0x09, 0x31, 583 /* Input (Var) */ 0x81, 0x02, 584 /* End Collection */ 0xC0, 585 /* 5 of 5 */ 586 /* Usage Page (Digitizer) */ 0x05, 0x0D, 587 /* Usage (Finger) */ 0x09, 0x22, 588 /* Collection (Logical) */ 0xA1, 0x02, 589 /* Usage (Tip Switch) */ 0x09, 0x42, 590 /* Logical Minimum (0) */ 0x15, 0x00, 591 /* Logical Maximum (1) */ 0x25, 0x01, 592 /* Report Size (1) */ 0x75, 0x01, 593 /* Report Count (1) */ 0x95, 0x01, 594 /* Input (Var) */ 0x81, 0x02, 595 /* Usage (In Range) */ 0x09, 0x32, 596 /* Logical Minimum (0) */ 0x15, 0x00, 597 /* Logical Maximum (1) */ 0x25, 0x01, 598 /* Report Size (1) */ 0x75, 0x01, 599 /* Report Count (1) */ 0x95, 0x01, 600 /* Input (Var) */ 0x81, 0x02, 601 /* Report Count (6) */ 0x95, 0x06, 602 /* Input (Cnst,Var) */ 0x81, 0x03, 603 /* Report Size (8) */ 0x75, 0x08, 604 /* Usage (Contact identifier) */ 0x09, 0x51, 605 /* Report Count (1) */ 0x95, 0x01, 606 /* Logical Minimum (0) */ 0x15, 0x00, 607 /* Logical Maximum (32) */ 0x25, 0x20, 608 /* Input (Var) */ 0x81, 0x02, 609 /* Usage Page (Generic Desktop) */ 0x05, 0x01, 610 /* Logical Maximum (32K) */ 0x26, 0xFF, 0x7F, 611 /* Report Size (16) */ 0x75, 0x10, 612 /* Usage (X) */ 0x09, 0x30, 613 /* Input (Var) */ 0x81, 0x02, 614 /* Usage (Y) */ 0x09, 0x31, 615 /* Input (Var) */ 0x81, 0x02, 616 /* End Collection */ 0xC0, 617 618 /* Note: "Scan time" usage is required for all touch devices (in 100microseconds units). */ 619 /* Usage Page (Digitizer) */ 0x05, 0x0D, 620 /* Logical Minimum (0) */ 0x17, 0x00, 0x00, 0x00, 0x00, 621 /* Logical Maximum (2147483647) */ 0x27, 0xFF, 0xFF, 0xFF, 0x7F, 622 /* Report Size (32) */ 0x75, 0x20, 623 /* Report Count (1) */ 0x95, 0x01, 624 /* Unit Exponent (0) */ 0x55, 0x00, 625 /* Unit (None) */ 0x65, 0x00, 626 /* Usage (Scan time) */ 0x09, 0x56, 627 /* Input (Var) */ 0x81, 0x02, 628 629 /* Report ID */ 0x85, REPORTID_TOUCH_MAX_COUNT, 630 /* Usage (Contact count maximum) */ 0x09, 0x55, 631 /* Usage (Device identifier) */ 0x09, 0x53, 632 /* Report Size (8) */ 0x75, 0x08, 633 /* Report Count (2) */ 0x95, 0x02, 634 /* Logical Maximum (255) */ 0x26, 0xFF, 0x00, 635 /* Feature (Var) */ 0xB1, 0x02, 636 637 /* Usage Page (Vendor-Defined 1) */ 0x06, 0x00, 0xFF, 638 /* Usage (QA blob) */ 0x09, 0xC5, 639 /* Report ID */ 0x85, REPORTID_TOUCH_QABLOB, 640 /* Logical Minimum (0) */ 0x15, 0x00, 641 /* Logical Maximum (255) */ 0x26, 0xFF, 0x00, 642 /* Report Size (8) */ 0x75, 0x08, 643 /* Report Count (256) */ 0x96, 0x00, 0x01, 644 /* Feature (Var) */ 0xB1, 0x02, 645 /* End Collection */ 0xC0, 646 647 /* Note: the pointer report is required by specification: 648 * "The report descriptor for a multiple input device must include at least 649 * one top-level collection for the primary device and a separate top-level 650 * collection for the mouse." 651 */ 652 /* Usage Page (Generic Desktop) */ 0x05, 0x01, 653 /* Usage (Pointer) */ 0x09, 0x01, 654 /* Collection (Application) */ 0xA1, 0x01, 655 /* Report ID */ 0x85, REPORTID_TOUCH_POINTER, 656 /* Usage (Pointer) */ 0x09, 0x01, 657 /* Collection (Logical) */ 0xA1, 0x02, 658 /* Usage Page (Button) */ 0x05, 0x09, 659 /* Usage Minimum (Button 1) */ 0x19, 0x01, 660 /* Usage Maximum (Button 2) */ 0x29, 0x02, 661 /* Logical Minimum (0) */ 0x15, 0x00, 662 /* Logical Maximum (1) */ 0x25, 0x01, 663 /* Report Count (2) */ 0x95, 0x02, 664 /* Report Size (1) */ 0x75, 0x01, 665 /* Input (Var) */ 0x81, 0x02, 666 /* Report Count (1) */ 0x95, 0x01, 667 /* Report Size (6) */ 0x75, 0x06, 668 /* Input (Cnst,Ary,Abs) */ 0x81, 0x01, 669 /* Usage Page (Generic Desktop) */ 0x05, 0x01, 670 /* Usage (X) */ 0x09, 0x30, 671 /* Usage (Y) */ 0x09, 0x31, 672 /* Logical Minimum (0) */ 0x16, 0x00, 0x00, 673 /* Logical Maximum (32K) */ 0x26, 0xFF, 0x7F, 674 /* Physical Minimum (0) */ 0x36, 0x00, 0x00, 675 /* Physical Maximum (32K) */ 0x46, 0xFF, 0x7F, 676 /* Unit (None) */ 0x66, 0x00, 0x00, 677 /* Report Size (16) */ 0x75, 0x10, 678 /* Report Count (2) */ 0x95, 0x02, 679 /* Input (Var) */ 0x81, 0x02, 680 /* End Collection */ 0xC0, 681 /* End Collection */ 0xC0, 682 683 /* Usage Page (Digitizer) */ 0x05, 0x0D, 684 /* Usage (Device configuration) */ 0x09, 0x0E, 685 /* Collection (Application) */ 0xA1, 0x01, 686 /* Report ID */ 0x85, REPORTID_TOUCH_DEVCONFIG, 687 /* Usage (Device settings) */ 0x09, 0x23, 688 /* Collection (Logical) */ 0xA1, 0x02, 689 /* Usage (Device mode) */ 0x09, 0x52, 690 /* Usage (Device identifier) */ 0x09, 0x53, 691 /* Logical Minimum (0) */ 0x15, 0x00, 692 /* Logical Maximum (10) */ 0x25, 0x0A, 693 /* Report Size (8) */ 0x75, 0x08, 694 /* Report Count (2) */ 0x95, 0x02, 695 /* Feature (Var) */ 0xB1, 0x02, 696 /* End Collection */ 0xC0, 697 /* End Collection */ 0xC0 425 698 }; 426 699 … … 455 728 /* .bLength = */ 0x09, 456 729 /* .bDescriptorType = */ 0x21, /* HID */ 457 /* .bcdHID = */ 0x10, 0x0 1, /* 1.1 */730 /* .bcdHID = */ 0x10, 0x02, /* 2.1 */ 458 731 /* .bCountryCode = */ 0, 459 732 /* .bNumDescriptors = */ 1, 460 733 /* .bDescriptorType = */ 0x22, /* Report */ 461 /* .wDescriptorLength = */ sizeof(g_UsbHidMTReportDesc), 0x00734 /* .wDescriptorLength = */ RT_LO_U8(sizeof(g_UsbHidMTReportDesc)), RT_HI_U8(sizeof(g_UsbHidMTReportDesc)) 462 735 }; 463 736 … … 520 793 /* .pvClass = */ &g_UsbHidMTIfHidDesc, 521 794 /* .cbClass = */ sizeof(g_UsbHidMTIfHidDesc), 522 &g_aUsbHid TEndpointDescs[0],795 &g_aUsbHidMTEndpointDescs[0], 523 796 /* .pIAD = */ NULL, 524 797 /* .cbIAD = */ 0 … … 740 1013 PVUSBURB pCur = pQueue->pHead; 741 1014 if (pCur == pUrb) 1015 { 742 1016 pQueue->pHead = pUrb->Dev.pNext; 1017 if (!pUrb->Dev.pNext) 1018 pQueue->ppTail = &pQueue->pHead; 1019 } 743 1020 else 744 1021 { … … 754 1031 if (!pCur) 755 1032 return false; 756 } 757 if (!pUrb->Dev.pNext) 758 pQueue->ppTail = &pQueue->pHead; 1033 if (!pUrb->Dev.pNext) 1034 pQueue->ppTail = &pCur->Dev.pNext; 1035 } 1036 pUrb->Dev.pNext = NULL; 759 1037 return true; 760 1038 } … … 919 1197 pReport->m.fButtons, cbCopy)); 920 1198 break; 921 case USBHIDMODE_MULTI_TOUCH:922 pReport->mt.idReport = REPORTID_MOUSE;923 pReport->mt.cContact = pAccumulated->u.MultiTouch.cContact;924 pReport->mt.x = pAccumulated->u.MultiTouch.x;925 pReport->mt.y = pAccumulated->u.MultiTouch.y;926 pReport->mt.fContact = pAccumulated->u.MultiTouch.fContact;927 928 cbCopy = sizeof(pReport->mt);929 LogRel3(("Multi-touch event, x=%u, y=%u, cContact=%u, fContact=%02x, report size %d\n",930 (unsigned)pReport->mt.x, (unsigned)pReport->mt.y,931 (unsigned)pReport->mt.cContact, (unsigned)pReport->mt.fContact,932 cbCopy));933 break;934 1199 } 935 1200 … … 940 1205 } 941 1206 1207 DECLINLINE(MTCONTACT *) usbHidFindMTContact(MTCONTACT *paContacts, size_t cContacts, 1208 uint8_t u8Mask, uint8_t u8Value) 1209 { 1210 size_t i; 1211 for (i = 0; i < cContacts; i++) 1212 { 1213 if ((paContacts[i].status & u8Mask) == u8Value) 1214 { 1215 return &paContacts[i]; 1216 } 1217 } 1218 1219 return NULL; 1220 } 1221 1222 static int usbHidSendMultiTouchReport(PUSBHID pThis, PVUSBURB pUrb) 1223 { 1224 uint8_t i; 1225 MTCONTACT *pRepContact; 1226 MTCONTACT *pCurContact; 1227 1228 /* Number of contacts to be reported. In hybrid mode the first report contains 1229 * total number of contacts and subsequent reports contain 0. 1230 */ 1231 uint8_t cContacts = 0; 1232 1233 Assert(pThis->fHasPendingChanges); 1234 1235 if (!pThis->fTouchReporting) 1236 { 1237 pThis->fTouchReporting = true; 1238 1239 /* Update the reporting state with the new current state. 1240 * Also mark all active contacts in reporting state as dirty, 1241 * that is they must be reported to the guest. 1242 */ 1243 for (i = 0; i < MT_CONTACT_MAX_COUNT; i++) 1244 { 1245 pRepContact = &pThis->aReportingContactState[i]; 1246 pCurContact = &pThis->aCurrentContactState[i]; 1247 1248 if (pCurContact->status & MT_CONTACT_S_ACTIVE) 1249 { 1250 if (pCurContact->status & MT_CONTACT_S_REUSED) 1251 { 1252 pCurContact->status &= ~MT_CONTACT_S_REUSED; 1253 1254 /* Keep x,y. Will report lost contact at this point. */ 1255 pRepContact->id = pCurContact->oldId; 1256 pRepContact->flags = 0; 1257 pRepContact->status = MT_CONTACT_S_REUSED; 1258 } 1259 else if (pThis->aCurrentContactState[i].status & MT_CONTACT_S_CANCELLED) 1260 { 1261 pCurContact->status &= ~(MT_CONTACT_S_CANCELLED | MT_CONTACT_S_ACTIVE); 1262 1263 /* Keep x,y. Will report lost contact at this point. */ 1264 pRepContact->id = pCurContact->id; 1265 pRepContact->flags = 0; 1266 pRepContact->status = 0; 1267 } 1268 else 1269 { 1270 if (pCurContact->flags == 0) 1271 { 1272 pCurContact->status &= ~MT_CONTACT_S_ACTIVE; /* Contact disapeared. */ 1273 } 1274 1275 pRepContact->x = pCurContact->x; 1276 pRepContact->y = pCurContact->y; 1277 pRepContact->id = pCurContact->id; 1278 pRepContact->flags = pCurContact->flags; 1279 pRepContact->status = 0; 1280 } 1281 1282 cContacts++; 1283 1284 pRepContact->status |= MT_CONTACT_S_DIRTY; 1285 } 1286 else 1287 { 1288 pRepContact->status = 0; 1289 } 1290 } 1291 } 1292 1293 /* Report current state. */ 1294 USBHIDMT_REPORT *p = (USBHIDMT_REPORT *)&pUrb->abData[0]; 1295 RT_ZERO(*p); 1296 1297 p->idReport = REPORTID_TOUCH_EVENT; 1298 p->cContacts = cContacts; 1299 1300 uint8_t iReportedContact; 1301 for (iReportedContact = 0; iReportedContact < MT_CONTACTS_PER_REPORT; iReportedContact++) 1302 { 1303 /* Find the next not reported contact. */ 1304 pRepContact = usbHidFindMTContact(pThis->aReportingContactState, RT_ELEMENTS(pThis->aReportingContactState), 1305 MT_CONTACT_S_DIRTY, MT_CONTACT_S_DIRTY); 1306 1307 if (!pRepContact) 1308 { 1309 LogRel3(("usbHid: no more touch contacts to report\n")); 1310 break; 1311 } 1312 1313 if (pRepContact->status & MT_CONTACT_S_REUSED) 1314 { 1315 /* Do not clear DIRTY flag for contacts which were reused. 1316 * Because two reports must be generated: 1317 * one for old contact off, and the second for new contact on. 1318 */ 1319 pRepContact->status &= ~MT_CONTACT_S_REUSED; 1320 } 1321 else 1322 { 1323 pRepContact->status &= ~MT_CONTACT_S_DIRTY; 1324 } 1325 1326 p->aContacts[iReportedContact].fContact = pRepContact->flags; 1327 p->aContacts[iReportedContact].cContact = pRepContact->id; 1328 p->aContacts[iReportedContact].x = pRepContact->x >> pThis->u8CoordShift; 1329 p->aContacts[iReportedContact].y = pRepContact->y >> pThis->u8CoordShift; 1330 } 1331 1332 p->u32ScanTime = pThis->u32LastTouchScanTime * 10; 1333 1334 Assert(iReportedContact > 0); 1335 1336 /* Reset TouchReporting if all contacts reported. */ 1337 pRepContact = usbHidFindMTContact(pThis->aReportingContactState, RT_ELEMENTS(pThis->aReportingContactState), 1338 MT_CONTACT_S_DIRTY, MT_CONTACT_S_DIRTY); 1339 1340 if (!pRepContact) 1341 { 1342 LogRel3(("usbHid: all touch contacts reported\n")); 1343 pThis->fTouchReporting = false; 1344 pThis->fHasPendingChanges = false; 1345 } 1346 else 1347 { 1348 pThis->fHasPendingChanges = true; 1349 } 1350 1351 LogRel3(("usbHid: reporting touch contact:\n%.*Rhxd\n", sizeof(USBHIDMT_REPORT), p)); 1352 return usbHidCompleteOk(pThis, pUrb, sizeof(USBHIDMT_REPORT)); 1353 } 1354 942 1355 /** 943 1356 * Sends a state report to the host if there is a pending URB. … … 946 1359 { 947 1360 PVUSBURB pUrb = usbHidQueueRemoveHead(&pThis->ToHostQueue); 1361 1362 if (pThis->enmMode == USBHIDMODE_MULTI_TOUCH) 1363 { 1364 /* This device uses a different reporting method and fHasPendingChanges maintenance. */ 1365 if (pUrb) 1366 return usbHidSendMultiTouchReport(pThis, pUrb); 1367 return VINF_SUCCESS; 1368 } 948 1369 949 1370 if (pUrb) … … 1030 1451 1031 1452 /** 1032 * @interface_method_impl{PDMIMOUSEPORT,pfnPutEventMT} 1033 */ 1034 static DECLCALLBACK(int) usbHidMousePutEventMT(PPDMIMOUSEPORT pInterface, 1035 uint32_t x, uint32_t y, 1036 uint32_t cContact, 1037 uint32_t fContact) 1038 { 1453 * @interface_method_impl{PDMIMOUSEPORT,pfnPutEventMultiTouch} 1454 */ 1455 static DECLCALLBACK(int) usbHidMousePutEventMultiTouch(PPDMIMOUSEPORT pInterface, 1456 uint8_t cContacts, 1457 const uint64_t *pau64Contacts, 1458 uint32_t u32ScanTime) 1459 { 1460 uint8_t i; 1461 uint8_t j; 1462 1463 /* Make a copy of new contacts */ 1464 MTCONTACT *paNewContacts = (MTCONTACT *)RTMemTmpAlloc(sizeof(MTCONTACT) * cContacts); 1465 if (!paNewContacts) 1466 return VERR_NO_MEMORY; 1467 1468 for (i = 0; i < cContacts; i++) 1469 { 1470 paNewContacts[i].x = RT_LO_U16(RT_LO_U32(pau64Contacts[i])); 1471 paNewContacts[i].y = RT_HI_U16(RT_LO_U32(pau64Contacts[i])); 1472 paNewContacts[i].id = RT_BYTE1(RT_HI_U32(pau64Contacts[i])); 1473 paNewContacts[i].flags = RT_BYTE2(RT_HI_U32(pau64Contacts[i])) & (MT_CONTACT_F_IN_CONTACT | MT_CONTACT_F_IN_RANGE); 1474 paNewContacts[i].status = MT_CONTACT_S_DIRTY; 1475 paNewContacts[i].oldId = 0; /* Not used. */ 1476 } 1477 1039 1478 PUSBHID pThis = RT_FROM_MEMBER(pInterface, USBHID, Lun0.IPort); 1040 if (pThis->fHasPendingChanges) 1041 return VERR_TRY_AGAIN; 1479 MTCONTACT *pCurContact = NULL; 1480 MTCONTACT *pNewContact = NULL; 1481 1042 1482 RTCritSectEnter(&pThis->CritSect); 1043 1483 1044 1484 Assert(pThis->enmMode == USBHIDMODE_MULTI_TOUCH); 1045 1485 1046 /* Accumulate movement - the events from the front end may arrive 1047 * at a much higher rate than USB can handle. Probably not a real issue 1048 * when only the Z axis is relative (X/Y movement isn't technically 1049 * accumulated and only the last value is used). 1486 /* Maintain a state of all current contacts. 1487 * Intr URBs will be completed according to the state. 1050 1488 */ 1051 pThis->PtrDelta.u.MultiTouch.fContact = fContact; 1052 pThis->PtrDelta.u.MultiTouch.x = x >> pThis->u8CoordShift; 1053 pThis->PtrDelta.u.MultiTouch.y = y >> pThis->u8CoordShift; 1054 pThis->PtrDelta.u.MultiTouch.cContact = cContact; 1489 1490 /* Mark all existing contacts as dirty. */ 1491 for (i = 0; i < RT_ELEMENTS(pThis->aCurrentContactState); i++) 1492 pThis->aCurrentContactState[i].status |= MT_CONTACT_S_DIRTY; 1493 1494 /* Update existing contacts and mark new contacts. */ 1495 for (i = 0; i < cContacts; i++) 1496 { 1497 pNewContact = &paNewContacts[i]; 1498 1499 /* Find existing contact with the same id. */ 1500 pCurContact = NULL; 1501 for (j = 0; j < RT_ELEMENTS(pThis->aCurrentContactState); j++) 1502 { 1503 if ( (pThis->aCurrentContactState[j].status & MT_CONTACT_S_ACTIVE) != 0 1504 && pThis->aCurrentContactState[j].id == pNewContact->id) 1505 { 1506 pCurContact = &pThis->aCurrentContactState[j]; 1507 break; 1508 } 1509 } 1510 1511 if (pCurContact) 1512 { 1513 pNewContact->status &= ~MT_CONTACT_S_DIRTY; 1514 1515 pCurContact->x = pNewContact->x; 1516 pCurContact->y = pNewContact->y; 1517 if (pCurContact->flags == 0) /* Contact disappeared already. */ 1518 { 1519 if ((pCurContact->status & MT_CONTACT_S_REUSED) == 0) 1520 { 1521 pCurContact->status |= MT_CONTACT_S_REUSED; /* Report to the guest that the contact not in touch. */ 1522 pCurContact->oldId = pCurContact->id; 1523 } 1524 } 1525 pCurContact->flags = pNewContact->flags; 1526 pCurContact->status &= ~MT_CONTACT_S_DIRTY; 1527 } 1528 } 1529 1530 /* Append new contacts (the dirty one in the paNewContacts). */ 1531 for (i = 0; i < cContacts; i++) 1532 { 1533 pNewContact = &paNewContacts[i]; 1534 1535 if (pNewContact->status & MT_CONTACT_S_DIRTY) 1536 { 1537 /* It is a new contact, copy is to one of not ACTIVE or not updated existing contacts. */ 1538 pCurContact = usbHidFindMTContact(pThis->aCurrentContactState, RT_ELEMENTS(pThis->aCurrentContactState), 1539 MT_CONTACT_S_ACTIVE, 0); 1540 1541 if (pCurContact) 1542 { 1543 *pCurContact = *pNewContact; 1544 pCurContact->status = MT_CONTACT_S_ACTIVE; /* Reset status. */ 1545 } 1546 else 1547 { 1548 /* Dirty existing contacts can be reused. */ 1549 pCurContact = usbHidFindMTContact(pThis->aCurrentContactState, RT_ELEMENTS(pThis->aCurrentContactState), 1550 MT_CONTACT_S_ACTIVE | MT_CONTACT_S_DIRTY, 1551 MT_CONTACT_S_ACTIVE | MT_CONTACT_S_DIRTY); 1552 1553 if (pCurContact) 1554 { 1555 pCurContact->x = pNewContact->x; 1556 pCurContact->y = pNewContact->y; 1557 if ((pCurContact->status & MT_CONTACT_S_REUSED) == 0) 1558 { 1559 pCurContact->status |= MT_CONTACT_S_REUSED; /* Report to the guest that the contact not in touch. */ 1560 pCurContact->oldId = pCurContact->id; 1561 } 1562 pCurContact->flags = pNewContact->flags; 1563 pCurContact->status &= ~MT_CONTACT_S_DIRTY; 1564 } 1565 else 1566 { 1567 LogRel3(("usbHid: dropped new contact: %d,%d id %d flags %RX8 status %RX8 oldId %d\n", 1568 pNewContact->x, 1569 pNewContact->y, 1570 pNewContact->id, 1571 pNewContact->flags, 1572 pNewContact->status, 1573 pNewContact->oldId 1574 )); 1575 } 1576 } 1577 } 1578 } 1579 1580 /* Mark still dirty existing contacts as cancelled, because a new set of contacts does not include them. */ 1581 for (i = 0; i < RT_ELEMENTS(pThis->aCurrentContactState); i++) 1582 { 1583 pCurContact = &pThis->aCurrentContactState[i]; 1584 if (pCurContact->status & MT_CONTACT_S_DIRTY) 1585 { 1586 pCurContact->status |= MT_CONTACT_S_CANCELLED; 1587 pCurContact->status &= ~MT_CONTACT_S_DIRTY; 1588 } 1589 } 1590 1591 pThis->u32LastTouchScanTime = u32ScanTime; 1592 1593 LogRel3(("usbHid: scanTime (ms): %d\n", pThis->u32LastTouchScanTime)); 1594 for (i = 0; i < RT_ELEMENTS(pThis->aCurrentContactState); i++) 1595 { 1596 LogRel3(("usbHid: contact state[%d]: %d,%d id %d flags %RX8 status %RX8 oldId %d\n", 1597 i, 1598 pThis->aCurrentContactState[i].x, 1599 pThis->aCurrentContactState[i].y, 1600 pThis->aCurrentContactState[i].id, 1601 pThis->aCurrentContactState[i].flags, 1602 pThis->aCurrentContactState[i].status, 1603 pThis->aCurrentContactState[i].oldId 1604 )); 1605 } 1606 1607 pThis->fHasPendingChanges = true; 1055 1608 1056 1609 /* Send a report if possible. */ … … 1058 1611 1059 1612 RTCritSectLeave(&pThis->CritSect); 1613 1614 RTMemTmpFree(paNewContacts); 1060 1615 return VINF_SUCCESS; 1061 1616 } … … 1067 1622 { 1068 1623 PUSBHID pThis = PDMINS_2_DATA(pUsbIns, PUSBHID); 1069 LogRelFlow(("usbHidUrbReap/#%u: cMillies=%u\n", pUsbIns->iInstance, cMillies));1070 1624 1071 1625 RTCritSectEnter(&pThis->CritSect); … … 1157 1711 case USBHIDREQSTATE_READY: 1158 1712 usbHidQueueAddTail(&pThis->ToHostQueue, pUrb); 1713 LogRelFlow(("usbHidHandleIntrDevToHost: Added %p:%s to the queue\n", 1714 pUrb, pUrb->pszDesc)); 1159 1715 /* If a report is pending, send it right away. */ 1160 1716 if (pThis->fHasPendingChanges) 1161 1717 usbHidSendReport(pThis); 1162 LogRelFlow(("usbHidHandleIntrDevToHost: Added %p:%s to the queue\n",1163 pUrb, pUrb->pszDesc));1164 1718 return VINF_SUCCESS; 1165 1719 … … 1174 1728 } 1175 1729 1730 #define GET_REPORT 0x01 1731 #define GET_IDLE 0x02 1732 #define GET_PROTOCOL 0x03 1733 #define SET_REPORT 0x09 1734 #define SET_IDLE 0x0A 1735 #define SET_PROTOCOL 0x0B 1736 1737 static uint8_t sau8QASampleBlob[256] = 1738 { 1739 0xfc, 0x28, 0xfe, 0x84, 0x40, 0xcb, 0x9a, 0x87, 1740 0x0d, 0xbe, 0x57, 0x3c, 0xb6, 0x70, 0x09, 0x88, 1741 0x07, 0x97, 0x2d, 0x2b, 0xe3, 0x38, 0x34, 0xb6, 1742 0x6c, 0xed, 0xb0, 0xf7, 0xe5, 0x9c, 0xf6, 0xc2, 1743 0x2e, 0x84, 0x1b, 0xe8, 0xb4, 0x51, 0x78, 0x43, 1744 0x1f, 0x28, 0x4b, 0x7c, 0x2d, 0x53, 0xaf, 0xfc, 1745 0x47, 0x70, 0x1b, 0x59, 0x6f, 0x74, 0x43, 0xc4, 1746 0xf3, 0x47, 0x18, 0x53, 0x1a, 0xa2, 0xa1, 0x71, 1747 0xc7, 0x95, 0x0e, 0x31, 0x55, 0x21, 0xd3, 0xb5, 1748 0x1e, 0xe9, 0x0c, 0xba, 0xec, 0xb8, 0x89, 0x19, 1749 0x3e, 0xb3, 0xaf, 0x75, 0x81, 0x9d, 0x53, 0xb9, 1750 0x41, 0x57, 0xf4, 0x6d, 0x39, 0x25, 0x29, 0x7c, 1751 0x87, 0xd9, 0xb4, 0x98, 0x45, 0x7d, 0xa7, 0x26, 1752 0x9c, 0x65, 0x3b, 0x85, 0x68, 0x89, 0xd7, 0x3b, 1753 0xbd, 0xff, 0x14, 0x67, 0xf2, 0x2b, 0xf0, 0x2a, 1754 0x41, 0x54, 0xf0, 0xfd, 0x2c, 0x66, 0x7c, 0xf8, 1755 0xc0, 0x8f, 0x33, 0x13, 0x03, 0xf1, 0xd3, 0xc1, 1756 0x0b, 0x89, 0xd9, 0x1b, 0x62, 0xcd, 0x51, 0xb7, 1757 0x80, 0xb8, 0xaf, 0x3a, 0x10, 0xc1, 0x8a, 0x5b, 1758 0xe8, 0x8a, 0x56, 0xf0, 0x8c, 0xaa, 0xfa, 0x35, 1759 0xe9, 0x42, 0xc4, 0xd8, 0x55, 0xc3, 0x38, 0xcc, 1760 0x2b, 0x53, 0x5c, 0x69, 0x52, 0xd5, 0xc8, 0x73, 1761 0x02, 0x38, 0x7c, 0x73, 0xb6, 0x41, 0xe7, 0xff, 1762 0x05, 0xd8, 0x2b, 0x79, 0x9a, 0xe2, 0x34, 0x60, 1763 0x8f, 0xa3, 0x32, 0x1f, 0x09, 0x78, 0x62, 0xbc, 1764 0x80, 0xe3, 0x0f, 0xbd, 0x65, 0x20, 0x08, 0x13, 1765 0xc1, 0xe2, 0xee, 0x53, 0x2d, 0x86, 0x7e, 0xa7, 1766 0x5a, 0xc5, 0xd3, 0x7d, 0x98, 0xbe, 0x31, 0x48, 1767 0x1f, 0xfb, 0xda, 0xaf, 0xa2, 0xa8, 0x6a, 0x89, 1768 0xd6, 0xbf, 0xf2, 0xd3, 0x32, 0x2a, 0x9a, 0xe4, 1769 0xcf, 0x17, 0xb7, 0xb8, 0xf4, 0xe1, 0x33, 0x08, 1770 0x24, 0x8b, 0xc4, 0x43, 0xa5, 0xe5, 0x24, 0xc2 1771 }; 1772 1773 static int usbHidRequestClass(PUSBHID pThis, PUSBHIDEP pEp, PVUSBURB pUrb) 1774 { 1775 PVUSBSETUP pSetup = (PVUSBSETUP)&pUrb->abData[0]; 1776 1777 if (pThis->enmMode != USBHIDMODE_MULTI_TOUCH) 1778 { 1779 LogRelFlow(("usbHid: bmRequestType=%#x bRequest=%#x wValue=%#x wIndex=%#x wLength=%#x\n", 1780 pSetup->bmRequestType, pSetup->bRequest, pSetup->wValue, 1781 pSetup->wIndex, pSetup->wLength)); 1782 return usbHidCompleteStall(pThis, pEp, pUrb, "Unsupported class req"); 1783 } 1784 1785 int rc = VINF_SUCCESS; 1786 1787 switch (pSetup->bRequest) 1788 { 1789 case SET_REPORT: 1790 case GET_REPORT: 1791 { 1792 uint8_t u8ReportType = RT_HI_U8(pSetup->wValue); 1793 uint8_t u8ReportID = RT_LO_U8(pSetup->wValue); 1794 LogRelFlow(("usbHid: %s: type %d, ID %d, data\n%.*Rhxd\n", 1795 pSetup->bRequest == GET_REPORT? "GET_REPORT": "SET_REPORT", 1796 u8ReportType, u8ReportID, 1797 pUrb->cbData - sizeof(VUSBSETUP), &pUrb->abData[sizeof(VUSBSETUP)])); 1798 uint32_t cbData = 0; 1799 if (pSetup->bRequest == GET_REPORT) 1800 { 1801 if (u8ReportType == 3 && u8ReportID == REPORTID_TOUCH_MAX_COUNT) 1802 { 1803 pUrb->abData[sizeof(VUSBSETUP) + 0] = REPORTID_TOUCH_MAX_COUNT; 1804 pUrb->abData[sizeof(VUSBSETUP) + 1] = MT_CONTACT_MAX_COUNT; /* Contact count maximum. */ 1805 pUrb->abData[sizeof(VUSBSETUP) + 2] = 0; /* Device identifier */ 1806 cbData = 3; 1807 } 1808 else if (u8ReportType == 3 && u8ReportID == REPORTID_TOUCH_QABLOB) 1809 { 1810 uint32_t cbLeft = pUrb->cbData; 1811 pUrb->abData[sizeof(VUSBSETUP) + 0] = REPORTID_TOUCH_QABLOB; /* Report Id. */ 1812 memcpy(&pUrb->abData[sizeof(VUSBSETUP) + 1], 1813 sau8QASampleBlob, sizeof(sau8QASampleBlob)); 1814 cbData = sizeof(sau8QASampleBlob) + 1; 1815 } 1816 } 1817 1818 rc = usbHidCompleteOk(pThis, pUrb, sizeof(VUSBSETUP) + cbData); 1819 } break; 1820 default: 1821 { 1822 LogRelFlow(("usbHid: bmRequestType=%#x bRequest=%#x wValue=%#x wIndex=%#x wLength=%#x\n", 1823 pSetup->bmRequestType, pSetup->bRequest, pSetup->wValue, 1824 pSetup->wIndex, pSetup->wLength)); 1825 rc = usbHidCompleteStall(pThis, pEp, pUrb, "Unsupported class req MT"); 1826 } 1827 } 1828 1829 return rc; 1830 } 1176 1831 1177 1832 /** … … 1363 2018 usbHidCompleteStall(pThis, pEp, pUrb, "TODO: standard request stuff"); 1364 2019 } 2020 else if ((pSetup->bmRequestType & VUSB_REQ_MASK) == VUSB_REQ_CLASS) 2021 { 2022 /* Only VUSB_TO_INTERFACE is allowed. */ 2023 if ((pSetup->bmRequestType & VUSB_RECIP_MASK) == VUSB_TO_INTERFACE) 2024 { 2025 return usbHidRequestClass(pThis, pEp, pUrb); 2026 } 2027 2028 LogRelFlow(("usbHid: invalid recipient of class req: bmRequestType=%#x bRequest=%#x wValue=%#x wIndex=%#x wLength=%#x\n", 2029 pSetup->bmRequestType, pSetup->bRequest, pSetup->wValue, 2030 pSetup->wIndex, pSetup->wLength)); 2031 return usbHidCompleteStall(pThis, pEp, pUrb, "Invalid recip"); 2032 } 1365 2033 else 1366 2034 { … … 1582 2250 pThis->Lun0.IPort.pfnPutEvent = usbHidMousePutEvent; 1583 2251 pThis->Lun0.IPort.pfnPutEventAbs = usbHidMousePutEventAbs; 1584 pThis->Lun0.IPort.pfnPutEventM T = usbHidMousePutEventMT;2252 pThis->Lun0.IPort.pfnPutEventMultiTouch = usbHidMousePutEventMultiTouch; 1585 2253 1586 2254 /* -
trunk/src/VBox/Devices/Input/testcase/tstUsbMouse.cpp
r47422 r47571 247 247 } 248 248 249 249 #if 0 250 /** @todo PDM interface was updated. This is not working anymore. */ 250 251 static void testSendPositionMT(RTTEST hTest) 251 252 { … … 296 297 g_UsbHidMou.pfnDestruct(pThis); 297 298 } 298 299 #endif 299 300 300 301 int main() … … 322 323 testSendPositionRel(hTest); 323 324 testSendPositionAbs(hTest); 324 testSendPositionMT(hTest);325 /* testSendPositionMT(hTest); */ 325 326 return RTTestSummaryAndDestroy(hTest); 326 327 } -
trunk/src/VBox/Frontends/VirtualBox/src/runtime/UIMouseHandler.cpp
r47511 r47571 62 62 #include "CFramebuffer.h" 63 63 #include "CDisplay.h" 64 65 #include <iprt/time.h> 64 66 65 67 /* Factory function to create mouse-handler: */ … … 907 909 CMouse mouse = session().GetConsole().GetMouse(); 908 910 911 QVector<LONG64> contacts(pTouchEvent->touchPoints().size()); 912 909 913 /* Pass all multi-touch events into guest: */ 914 int i = 0; 910 915 foreach (const QTouchEvent::TouchPoint &touchPoint, pTouchEvent->touchPoints()) 911 916 { … … 929 934 LogRelFlow(("UIMouseHandler::multiTouchEvent: Origin: %dx%d, State: %d\n", 930 935 currentTouchPoint.x(), currentTouchPoint.y(), iTouchPointState)); 931 mouse.PutMouseEventMultiTouch((LONG)currentTouchPoint.x(), (LONG)currentTouchPoint.y(), 932 (LONG)touchPoint.id(), iTouchPointState); 933 } 936 937 contacts[i++] = RT_MAKE_U64_FROM_U16((uint16_t)currentTouchPoint.x(), 938 (uint16_t)currentTouchPoint.y(), 939 RT_MAKE_U16(touchPoint.id(), iTouchPointState), 940 0); 941 } 942 943 mouse.PutEventMultiTouch(pTouchEvent->touchPoints().size(), 944 contacts, 945 (ULONG)RTTimeMilliTS()); 934 946 935 947 /* Eat by default? */ -
trunk/src/VBox/Main/idl/VirtualBox.xidl
r47561 r47571 14494 14494 <interface 14495 14495 name="IMouse" extends="$unknown" 14496 uuid=" b84498e5-c8ad-4ae0-adbe-7928c7a546df"14496 uuid="ee770393-415f-4421-b2d5-28b73cacf86a" 14497 14497 wsmap="managed" 14498 14498 > … … 14672 14672 </method> 14673 14673 14674 <method name="put MouseEventMultiTouch">14675 <desc> 14676 Sends a multi-touch pointer event. 14674 <method name="putEventMultiTouch"> 14675 <desc> 14676 Sends a multi-touch pointer event. The coordinates are expressed in 14677 14677 pixels and start from <tt>[1,1]</tt> which corresponds to the top left 14678 14678 corner of the virtual display. … … 14682 14682 </result> 14683 14683 <result name="VBOX_E_IPRT_ERROR"> 14684 Could not send mouse event to virtual mouse.14684 Could not send event to virtual device. 14685 14685 </result> 14686 14686 … … 14692 14692 </desc> 14693 14693 14694 <param name="x" type="long" dir="in"> 14695 <desc> 14696 X coordinate of the touch in pixels, starting from @c 1. 14697 </desc> 14698 </param> 14699 <param name="y" type="long" dir="in"> 14700 <desc> 14701 Y coordinate of the touch in pixels, starting from @c 1. 14702 </desc> 14703 </param> 14704 <param name="contactID" type="long" dir="in"> 14705 <desc> 14706 Identifier for the touch number. When a touch starts (i.e. a finger 14707 first touches the device) it is given a currently unused identifier, 14708 but if the touch moves without interruption (i.e. the finger is 14709 touching the device the whole time) the identifier will be the same 14710 for all following events. 14711 </desc> 14712 </param> 14713 <param name="contactState" type="long" dir="in"> 14714 <desc> 14715 State information for the touch identified by @a contactID. See the 14716 <link to="TouchContactState"/> enumeration value. If this is not 14717 zero, expect more events with the same @a contactID, and this will 14718 usually be zero when the last event is received before the contact is 14719 stopped (i.e. the finger is removed from the device). 14694 <param name="count" type="long" dir="in"> 14695 <desc> 14696 Number of contacts in the event. 14697 </desc> 14698 </param> 14699 14700 <param name="contacts" type="long long" dir="in" safearray="yes"> 14701 <desc> 14702 Each array element contains packed information about one contact. 14703 Bits 0..15: X coordinate in pixels. 14704 Bits 16..31: Y coordinate in pixels. 14705 Bits 32..39: contact identifier. 14706 Bit 40: "in contact" flag, which indicates that there is a contact with the touch surface. 14707 Bit 41: "in range" flag, the contact is close enough to the touch surface. 14708 All other bits are reserved for future use and must be set to 0. 14709 </desc> 14710 </param> 14711 14712 <param name="scanTime" type="unsigned long" dir="in"> 14713 <desc> 14714 Timestamp of the event in milliseconds. Only relative time between events is important. 14715 </desc> 14716 </param> 14717 </method> 14718 14719 <method name="putEventMultiTouchString"> 14720 <desc> 14721 <see><link to="#putEventMultiTouch"/></see> 14722 </desc> 14723 14724 <param name="count" type="long" dir="in"> 14725 <desc> 14726 <see><link to="#putEventMultiTouch"/></see> 14727 </desc> 14728 </param> 14729 14730 <param name="contacts" type="wstring" dir="in"> 14731 <desc> 14732 Contains information about all contacts: 14733 "id1,x1,y1,inContact1,inRange1;...;idN,xN,yN,inContactN,inRangeN". 14734 For example for two contacts: "0,10,20,1,1;1,30,40,1,1" 14735 </desc> 14736 </param> 14737 14738 <param name="scanTime" type="unsigned long" dir="in"> 14739 <desc> 14740 <see><link to="#putEventMultiTouch"/></see> 14720 14741 </desc> 14721 14742 </param> -
trunk/src/VBox/Main/include/ConsoleVRDPServer.h
r47464 r47571 356 356 const void *pvEvent, 357 357 uint32_t cbEvent); 358 uint64_t mu64TouchInputTimestampMCS; 358 359 }; 359 360 -
trunk/src/VBox/Main/include/MouseImpl.h
r47245 r47571 66 66 STDMETHOD(PutMouseEventAbsolute)(LONG x, LONG y, LONG dz, LONG dw, 67 67 LONG buttonState); 68 STDMETHOD(Put MouseEventMultiTouch)(LONG x, LONG y, LONG contactID,69 LONG contactState);68 STDMETHOD(PutEventMultiTouch)(LONG aCount, ComSafeArrayIn(LONG64, aContacts), ULONG aScanTime); 69 STDMETHOD(PutEventMultiTouchString)(LONG aCount, IN_BSTR aContacts, ULONG aScanTime); 70 70 STDMETHOD(COMGETTER(EventSource)) (IEventSource ** aEventSource); 71 71 … … 98 98 HRESULT reportMTEventToMouseDev(int32_t x, int32_t z, uint32_t cContact, 99 99 uint32_t fContact); 100 HRESULT reportMultiTouchEventToDevice(uint8_t cContacts, const uint64_t *pau64Contacts, uint32_t u32ScanTime); 100 101 HRESULT reportAbsEventToVMMDev(int32_t x, int32_t y); 101 102 HRESULT reportAbsEvent(int32_t x, int32_t y, int32_t dz, int32_t dw, … … 103 104 HRESULT convertDisplayRes(LONG x, LONG y, int32_t *pxAdj, int32_t *pyAdj, 104 105 bool *pfValid); 106 HRESULT putEventMultiTouch(LONG aCount, LONG64 *paContacts, ULONG aScanTime); 105 107 106 108 void getDeviceCaps(bool *pfAbs, bool *pfRel, bool *fMT); -
trunk/src/VBox/Main/src-client/ConsoleVRDPServer.cpp
r47464 r47571 2815 2815 if (pHeader->u16EventId == VRDEINPUT_EVENTID_TOUCH) 2816 2816 { 2817 IMouse *pMouse = pThis->mConsole->getMouse(); 2818 2817 2819 VRDEINPUT_TOUCH_EVENT_PDU *p = (VRDEINPUT_TOUCH_EVENT_PDU *)pHeader; 2818 2820 … … 2822 2824 VRDEINPUT_TOUCH_FRAME *pFrame = &p->aFrames[iFrame]; 2823 2825 2826 com::SafeArray<LONG64> aContacts(pFrame->u16ContactCount); 2827 2824 2828 uint16_t iContact; 2825 2829 for (iContact = 0; iContact < pFrame->u16ContactCount; iContact++) … … 2827 2831 VRDEINPUT_CONTACT_DATA *pContact = &pFrame->aContacts[iContact]; 2828 2832 2829 LONG x = pContact->i32X; 2830 LONG y = pContact->i32Y; 2831 LONG cContact = pContact->u8ContactId; 2832 LONG contactState = TouchContactState_None; 2833 2834 /* @todo */ 2833 int16_t x = (int16_t)(pContact->i32X + 1); 2834 int16_t y = (int16_t)(pContact->i32Y + 1); 2835 uint8_t contactId = pContact->u8ContactId; 2836 uint8_t contactState = TouchContactState_None; 2837 2835 2838 if (pContact->u32ContactFlags & VRDEINPUT_CONTACT_FLAG_INRANGE) 2836 2839 { … … 2841 2844 contactState |= TouchContactState_InContact; 2842 2845 } 2843 2844 HRESULT hrc = pThis->mConsole->getMouse()->PutMouseEventMultiTouch(x, y, cContact, contactState); 2846 2847 aContacts[iContact] = RT_MAKE_U64_FROM_U16((uint16_t)x, 2848 (uint16_t)y, 2849 RT_MAKE_U16(contactId, contactState), 2850 0); 2845 2851 } 2852 2853 if (pFrame->u64FrameOffset == 0) 2854 { 2855 pThis->mu64TouchInputTimestampMCS = 0; 2856 } 2857 else 2858 { 2859 pThis->mu64TouchInputTimestampMCS += pFrame->u64FrameOffset; 2860 } 2861 2862 pMouse->PutEventMultiTouch(pFrame->u16ContactCount, 2863 ComSafeArrayAsInParam(aContacts), 2864 (ULONG)(pThis->mu64TouchInputTimestampMCS / 1000)); /* Micro->milliseconds. */ 2846 2865 } 2847 2866 } -
trunk/src/VBox/Main/src-client/MouseImpl.cpp
r47358 r47571 362 362 } 363 363 364 365 /** 366 * Send a multi-touch event to the first enabled emulated multi-touch device. 367 * 368 * @returns COM status code 369 */ 370 HRESULT Mouse::reportMTEventToMouseDev(int32_t x, int32_t y, 371 uint32_t cContact, uint32_t fContact) 372 { 373 if ( x < VMMDEV_MOUSE_RANGE_MIN 374 || x > VMMDEV_MOUSE_RANGE_MAX) 375 return S_OK; 376 if ( y < VMMDEV_MOUSE_RANGE_MIN 377 || y > VMMDEV_MOUSE_RANGE_MAX) 378 return S_OK; 364 HRESULT Mouse::reportMultiTouchEventToDevice(uint8_t cContacts, 365 const uint64_t *pau64Contacts, 366 uint32_t u32ScanTime) 367 { 368 HRESULT hrc = S_OK; 369 379 370 PPDMIMOUSEPORT pUpPort = NULL; 380 371 { 381 372 AutoReadLock aLock(this COMMA_LOCKVAL_SRC_POS); 382 373 383 for (unsigned i = 0; !pUpPort && i < MOUSE_MAX_DEVICES; ++i) 374 unsigned i; 375 for (i = 0; i < MOUSE_MAX_DEVICES; ++i) 384 376 { 385 377 if ( mpDrv[i] 386 378 && (mpDrv[i]->u32DevCaps & MOUSE_DEVCAP_MULTI_TOUCH)) 379 { 387 380 pUpPort = mpDrv[i]->pUpPort; 381 break; 382 } 388 383 } 389 384 } 390 if (!pUpPort) 391 return S_OK; 392 393 int vrc = pUpPort->pfnPutEventMT(pUpPort, x, y, 394 cContact, fContact); 395 if (RT_FAILURE(vrc)) 396 return setError(VBOX_E_IPRT_ERROR, 397 tr("Could not send the touch event to the virtual device (%Rrc)"), 398 vrc); 399 return S_OK; 385 386 if (pUpPort) 387 { 388 int vrc = pUpPort->pfnPutEventMultiTouch(pUpPort, cContacts, pau64Contacts, u32ScanTime); 389 if (RT_FAILURE(vrc)) 390 hrc = setError(VBOX_E_IPRT_ERROR, 391 tr("Could not send the multi-touch event to the virtual device (%Rrc)"), 392 vrc); 393 } 394 else 395 { 396 hrc = E_UNEXPECTED; 397 } 398 399 return hrc; 400 400 } 401 401 … … 638 638 639 639 /** 640 * @interface_method_impl{IMouse,putMouseEventMultiTouch} 641 */ 642 STDMETHODIMP Mouse::PutMouseEventMultiTouch(LONG x, LONG y, LONG cContact, 643 LONG contactState) 640 * Send a multi-touch event. This requires multi-touch pointing device emulation. 641 * @note all calls out of this object are made with no locks held! 642 * 643 * @returns COM status code. 644 * @param aCount Number of contacts. 645 * @param aContacts Information about each contact. 646 * @param aScanTime Timestamp. 647 */ 648 STDMETHODIMP Mouse::PutEventMultiTouch(LONG aCount, 649 ComSafeArrayIn(LONG64, aContacts), 650 ULONG aScanTime) 644 651 { 645 652 AutoCaller autoCaller(this); 646 653 if (FAILED(autoCaller.rc())) return autoCaller.rc(); 647 654 648 LogRel3(("%s: x=%d, y=%d, cContact=%d, contactState=%d\n", 649 __PRETTY_FUNCTION__, x, y, cContact, contactState)); 650 651 int32_t xAdj, yAdj; 652 bool fValid; 653 654 /** @todo the front end should do this conversion to avoid races */ 655 /** @note Or maybe not... races are pretty inherent in everything done in 656 * this object and not really bad as far as I can see. */ 657 HRESULT rc = convertDisplayRes(x, y, &xAdj, &yAdj, &fValid); 658 if (FAILED(rc)) return rc; 659 660 if (fValid) 661 { 662 rc = reportMTEventToMouseDev(xAdj, yAdj, cContact, contactState); 663 664 fireMouseEvent(true, x, y, 0, 0, cContact, contactState); 655 com::SafeArray <LONG64> arrayContacts(ComSafeArrayInArg(aContacts)); 656 657 LogRel3(("%s: aCount %d(actual %d), aScanTime %u\n", 658 __FUNCTION__, aCount, arrayContacts.size(), aScanTime)); 659 660 HRESULT rc = S_OK; 661 662 if ((LONG)arrayContacts.size() >= aCount) 663 { 664 LONG64* paContacts = arrayContacts.raw(); 665 666 rc = putEventMultiTouch(aCount, paContacts, aScanTime); 667 } 668 else 669 { 670 rc = E_INVALIDARG; 665 671 } 666 672 667 673 return rc; 668 674 } 675 676 /** 677 * Send a multi-touch event. Version for scripting languages. 678 * 679 * @returns COM status code. 680 * @param aCount Number of contacts. 681 * @param aContacts Information about each contact. 682 * @param aScanTime Timestamp. 683 */ 684 STDMETHODIMP Mouse::PutEventMultiTouchString(LONG aCount, 685 IN_BSTR aContacts, 686 ULONG aScanTime) 687 { 688 /** @todo implement: convert the string to LONG64 array and call putEventMultiTouch. */ 689 NOREF(aCount); 690 NOREF(aContacts); 691 NOREF(aScanTime); 692 return E_NOTIMPL; 693 } 694 669 695 670 696 // private methods 671 697 ///////////////////////////////////////////////////////////////////////////// 698 699 /* Used by PutEventMultiTouch and PutEventMultiTouchString. */ 700 HRESULT Mouse::putEventMultiTouch(LONG aCount, 701 LONG64 *paContacts, 702 ULONG aScanTime) 703 { 704 if (aCount >= 256) 705 { 706 return E_INVALIDARG; 707 } 708 709 DisplayMouseInterface *pDisplay = mParent->getDisplayMouseInterface(); 710 ComAssertRet(pDisplay, E_FAIL); 711 712 HRESULT rc = S_OK; 713 714 uint64_t* pau64Contacts = NULL; 715 uint8_t cContacts = 0; 716 717 /* Deliver 0 contacts too, touch device may use this to reset the state. */ 718 if (aCount > 0) 719 { 720 /* Create a copy with converted coords. */ 721 pau64Contacts = (uint64_t *)RTMemTmpAlloc(aCount * sizeof(uint64_t)); 722 if (pau64Contacts) 723 { 724 int32_t x1, y1, x2, y2; 725 /* Takes the display lock */ 726 pDisplay->getFramebufferDimensions(&x1, &y1, &x2, &y2); 727 728 LONG i; 729 for (i = 0; i < aCount; i++) 730 { 731 int32_t x = (int16_t)RT_LO_U16(RT_LO_U32(paContacts[i])); 732 int32_t y = (int16_t)RT_HI_U16(RT_LO_U32(paContacts[i])); 733 uint8_t contactId = RT_BYTE1(RT_HI_U32(paContacts[i])); 734 bool fInContact = (RT_BYTE2(RT_HI_U32(paContacts[i])) & 0x1) != 0; 735 bool fInRange = (RT_BYTE2(RT_HI_U32(paContacts[i])) & 0x2) != 0; 736 737 LogRel3(("%s: [%d] %d,%d id %d, inContact %d, inRange %d\n", 738 __FUNCTION__, i, x, y, fInContact, fInRange)); 739 740 /* Framebuffer dimensions are 0,0 width, height, that is x2,y2 are exclusive, 741 * while coords are inclusive. 742 */ 743 int32_t xAdj = x1 < x2 ? ((x - 1 - x1) * VMMDEV_MOUSE_RANGE) 744 / (x2 - x1) : 0; 745 int32_t yAdj = y1 < y2 ? ((y - 1 - y1) * VMMDEV_MOUSE_RANGE) 746 / (y2 - y1) : 0; 747 748 bool fValid = ( xAdj >= VMMDEV_MOUSE_RANGE_MIN 749 && xAdj <= VMMDEV_MOUSE_RANGE_MAX 750 && yAdj >= VMMDEV_MOUSE_RANGE_MIN 751 && yAdj <= VMMDEV_MOUSE_RANGE_MAX); 752 753 if (fValid) 754 { 755 uint8_t fu8 = (fInContact? 0x01: 0x00) 756 | (fInRange? 0x02: 0x00); 757 pau64Contacts[cContacts] = RT_MAKE_U64_FROM_U16((uint16_t)xAdj, 758 (uint16_t)yAdj, 759 RT_MAKE_U16(contactId, fu8), 760 0); 761 cContacts++; 762 } 763 } 764 } 765 else 766 { 767 rc = E_OUTOFMEMORY; 768 } 769 } 770 771 if (SUCCEEDED(rc)) 772 { 773 rc = reportMultiTouchEventToDevice(cContacts, cContacts? pau64Contacts: NULL, (uint32_t)aScanTime); 774 775 // @todo Implement. Maybe using a new TouchEvent rather than extending the mouse event. 776 // fireMouseEvent(true, x, y, 0, 0, cContact, contactState); 777 } 778 779 RTMemTmpFree(pau64Contacts); 780 781 return rc; 782 } 672 783 673 784
Note:
See TracChangeset
for help on using the changeset viewer.