Changeset 80039 in vbox for trunk/src/VBox/Devices/Input
- Timestamp:
- Jul 29, 2019 10:31:03 AM (6 years ago)
- svn:sync-xref-src-repo-rev:
- 132475
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Devices/Input/PS2M.cpp
r76553 r80039 52 52 * commands with arguments 200, 200, 80 switch to ImEx mode. The Read ID (0F2h) 53 53 * command will report the currently selected protocol. 54 * 55 * There is an extended ImEx mode with support for horizontal scrolling. It is 56 * entered from ImEx mode with a 200, 80, 40 sequence of Set Sampling Rate 57 * commands. It does not change the reported protocol (it remains 4, or ImEx) 58 * but changes the meaning of the 4th byte. 54 59 * 55 60 * … … 90 95 * | Byte 4 | 0 | 0 | Btn 5 | Btn 4 | Z mov't delta (two's complement) | 91 96 * +--------+--------+--------+--------+--------+--------+--------+--------+--------+ 92 * 97 * 98 * - The Z delta values are in practice only -1/+1; some mice (A4tech?) report 99 * horizontal scrolling as -2/+2. 100 * 101 * IntelliMouse Explorer (ImEx) fourth report packet byte when scrolling: 102 * 103 * +--------+--------+--------+--------+--------+--------+--------+--------+--------+ 104 * |Bit/byte| bit 7 | bit 6 | bit 5 | bit 4 | bit 3 | bit 2 | bit 1 | bit 0 | 105 * +--------+--------+--------+--------+--------+--------+--------+--------+--------+ 106 * | Byte 4 | V | H | Z or W movement delta (two's complement) | 107 * +--------+--------+--------+--------+--------+--------+--------+--------+--------+ 108 * 109 * - Buttons 4 and 5 are reported as with the regular ImEx protocol, but not when 110 * scrolling. This is a departure from the usual logic because when the mouse 111 * sends scroll events, the state of buttons 4/5 is not reported and the last 112 * reported state should be assumed. 113 * 114 * - When the V bit (bit 7) is set, vertical scroll (Z axis) is being reported. 115 * When the H bit (bit 6) is set, horizontal scroll (W axis) is being reported. 116 * The H and V bits are never set at the same time (also see below). When 117 * the H and V bits are both clear, button 4/5 state is being reported. 118 * 119 * - The Z/W delta is extended to 6 bits. Z (vertical) values are not restricted 120 * to -1/+1, although W (horizontal) values are. Z values of at least -20/+20 121 * can be seen in practice. 122 * 123 * - Horizontal and vertical scroll is mutually exclusive. When the button is 124 * tilted, no vertical scrolling is reported, i.e. horizontal scrolling 125 * has priority over vertical. 126 * 127 * - Positive values indicate down/right direction, negative values up/left. 128 * 129 * - When the scroll button is tilted to engage horizontal scrolling, the mouse 130 * keeps sending events at a rate of 4 or 5 per second as long as the button 131 * is tilted. 132 * 133 * All report formats were verified with a real Microsoft IntelliMouse Explorer 4.0 134 * mouse attached through a PS/2 port. 135 * 136 * The button "accumulator" is necessary to avoid missing brief button presses. 137 * Without it, a very fast mouse button press + release might be lost if it 138 * happened between sending reports. The accumulator latches button presses to 139 * prevent that. 140 * 93 141 */ 94 142 … … 197 245 /* Protocols supported by the PS/2 mouse. */ 198 246 typedef enum { 199 PS2M_PROTO_PS2STD = 0, /* Standard PS/2 mouse protocol. */ 200 PS2M_PROTO_IMPS2 = 3, /* IntelliMouse PS/2 protocol. */ 201 PS2M_PROTO_IMEX = 4 /* IntelliMouse Explorer protocol. */ 247 PS2M_PROTO_PS2STD = 0, /* Standard PS/2 mouse protocol. */ 248 PS2M_PROTO_IMPS2 = 3, /* IntelliMouse PS/2 protocol. */ 249 PS2M_PROTO_IMEX = 4, /* IntelliMouse Explorer protocol. */ 250 PS2M_PROTO_IMEX_HORZ = 5 /* IntelliMouse Explorer with horizontal reports. */ 202 251 } PS2M_PROTO; 203 252 … … 207 256 PS2M_KNOCK_1ST, 208 257 PS2M_KNOCK_IMPS2_2ND, 209 PS2M_KNOCK_IMEX_2ND 258 PS2M_KNOCK_IMEX_2ND, 259 PS2M_KNOCK_IMEX_HORZ_2ND 210 260 } PS2M_KNOCK_STATE; 211 261 … … 243 293 /** Accumulated vertical movement. */ 244 294 int32_t iAccumY; 245 /** Accumulated Z axis movement. */295 /** Accumulated Z axis (vertical scroll) movement. */ 246 296 int32_t iAccumZ; 297 /** Accumulated W axis (horizontal scroll) movement. */ 298 int32_t iAccumW; 247 299 /** Accumulated button presses. */ 248 300 uint32_t fAccumB; … … 476 528 /* Event queue, eccumulators, and button status bits are cleared. */ 477 529 ps2kClearQueue((GeneriQ *)&pThis->evtQ); 478 pThis->iAccumX = pThis->iAccumY = pThis->iAccumZ = pThis-> fAccumB;530 pThis->iAccumX = pThis->iAccumY = pThis->iAccumZ = pThis->iAccumW = pThis->fAccumB = 0; 479 531 } 480 532 … … 493 545 else if (rate == 200) 494 546 pThis->enmKnockState = PS2M_KNOCK_IMEX_2ND; 547 else if (rate == 80) 548 pThis->enmKnockState = PS2M_KNOCK_IMEX_HORZ_2ND; 495 549 else 496 550 pThis->enmKnockState = PS2M_KNOCK_INITIAL; … … 510 564 LogRelFlow(("PS2M: Switching mouse to ImEx protocol.\n")); 511 565 } 566 pThis->enmKnockState = PS2M_KNOCK_INITIAL; 567 break; 568 case PS2M_KNOCK_IMEX_HORZ_2ND: 569 if (rate == 40) 570 { 571 pThis->enmProtocol = PS2M_PROTO_IMEX_HORZ; 572 LogRelFlow(("PS2M: Switching mouse ImEx with horizontal scrolling.\n")); 573 } 512 574 RT_FALL_THRU(); 513 575 default: … … 518 580 /* Three-button event mask. */ 519 581 #define PS2M_STD_BTN_MASK (RT_BIT(0) | RT_BIT(1) | RT_BIT(2)) 582 /* ImEx button 4/5 event mask. */ 583 #define PS2M_IMEX_BTN_MASK (RT_BIT(3) | RT_BIT(4)) 520 584 521 585 /* Report accumulated movement and button presses, then clear the accumulators. */ … … 524 588 uint32_t fBtnState = fAccumBtns ? pThis->fAccumB : pThis->fCurrB; 525 589 uint8_t val; 526 int dX, dY, dZ ;590 int dX, dY, dZ, dW; 527 591 528 592 /* Clamp the accumulated delta values to the allowed range. */ 529 593 dX = RT_MIN(RT_MAX(pThis->iAccumX, -255), 255); 530 594 dY = RT_MIN(RT_MAX(pThis->iAccumY, -255), 255); 531 dZ = RT_MIN(RT_MAX(pThis->iAccumZ, -8), 7);532 595 533 596 /* Start with the sync bit and buttons 1-3. */ … … 544 607 ps2kInsertQueue(pQueue, dY); 545 608 546 /* Add fourth byte if extended protocol is in use. */609 /* Add fourth byte if an extended protocol is in use. */ 547 610 if (pThis->enmProtocol > PS2M_PROTO_PS2STD) 548 611 { 612 /* Start out with 4-bit dZ range. */ 613 dZ = RT_MIN(RT_MAX(pThis->iAccumZ, -8), 7); 614 549 615 if (pThis->enmProtocol == PS2M_PROTO_IMPS2) 616 { 617 /* NB: Only uses 4-bit dZ range, despite using a full byte. */ 550 618 ps2kInsertQueue(pQueue, dZ); 619 pThis->iAccumZ -= dZ; 620 } 621 else if (pThis->enmProtocol == PS2M_PROTO_IMEX) 622 { 623 /* Z value uses 4 bits; buttons 4/5 in bits 4 and 5. */ 624 val = (fBtnState & PS2M_IMEX_BTN_MASK) << 1; 625 val |= dZ & 0x0f; 626 pThis->iAccumZ -= dZ; 627 ps2kInsertQueue(pQueue, val); 628 } 551 629 else 552 630 { 553 Assert(pThis->enmProtocol == PS2M_PROTO_IMEX); 554 /* Z value uses 4 bits; buttons 4/5 in bits 4 and 5. */ 555 val = dZ & 0x0f; 556 val |= (fBtnState << 1) & (RT_BIT(4) | RT_BIT(5)); 631 Assert((pThis->enmProtocol == PS2M_PROTO_IMEX_HORZ)); 632 /* With ImEx + horizontal reporting, prioritize buttons 4/5. */ 633 if (pThis->iAccumZ || pThis->iAccumW) 634 { 635 /* ImEx + horizontal reporting Horizontal scroll has 636 * precedence over vertical. Buttons cannot be reported 637 * this way. 638 */ 639 if (pThis->iAccumW) 640 { 641 dW = RT_MIN(RT_MAX(pThis->iAccumW, -32), 31); 642 val = (dW & 0x3F) | 0x40; 643 pThis->iAccumW -= dW; 644 } 645 else 646 { 647 Assert(pThis->iAccumZ); 648 /* We can use 6-bit dZ range. Wow! */ 649 dZ = RT_MIN(RT_MAX(pThis->iAccumZ, -32), 31); 650 val = (dZ & 0x3F) | 0x80; 651 pThis->iAccumZ -= dZ; 652 } 653 } 654 else 655 { 656 /* Just Buttons 4/5 in bits 4 and 5. No scrolling. */ 657 val = (fBtnState & PS2M_IMEX_BTN_MASK) << 1; 658 } 557 659 ps2kInsertQueue(pQueue, val); 558 660 } … … 560 662 561 663 /* Clear the movement accumulators, but not necessarily button state. */ 562 pThis->iAccumX = pThis->iAccumY = pThis->iAccumZ =0;664 pThis->iAccumX = pThis->iAccumY = 0; 563 665 /* Clear accumulated button state only when it's being used. */ 564 666 if (fAccumBtns) 565 667 { 566 pThis->fReportedB = pThis->f AccumB;668 pThis->fReportedB = pThis->fCurrB | pThis->fAccumB; 567 669 pThis->fAccumB = 0; 568 670 } … … 675 777 case ACMD_READ_ID: 676 778 ps2kInsertQueue((GeneriQ *)&pThis->cmdQ, ARSP_ACK); 677 ps2kInsertQueue((GeneriQ *)&pThis->cmdQ, pThis->enmProtocol); 779 /* ImEx + horizontal is protocol 4, just like plain ImEx. */ 780 u8Val = pThis->enmProtocol == PS2M_PROTO_IMEX_HORZ ? PS2M_PROTO_IMEX : pThis->enmProtocol; 781 ps2kInsertQueue((GeneriQ *)&pThis->cmdQ, u8Val); 678 782 pThis->u8CurrCmd = 0; 679 783 break; … … 840 944 static uint32_t ps2mHaveEvents(PPS2M pThis) 841 945 { 842 return pThis->iAccumX | pThis->iAccumY | pThis->iAccumZ843 | (pThis->fCurrB != pThis->fReportedB) | (pThis->fAccumB != 0);946 return pThis->iAccumX || pThis->iAccumY || pThis->iAccumZ || pThis->iAccumW 947 || ((pThis->fCurrB | pThis->fAccumB) != pThis->fReportedB); 844 948 } 845 949 … … 902 1006 { 903 1007 static const char *pcszModes[] = { "normal", "reset", "wrap" }; 904 static const char *pcszProtocols[] = { "PS/2", NULL, NULL, "ImPS/2", "ImEx" };1008 static const char *pcszProtocols[] = { "PS/2", NULL, NULL, "ImPS/2", "ImEx", "ImEx+horizontal" }; 905 1009 PPS2M pThis = KBDGetPS2MFromDevIns(pDevIns); 906 1010 NOREF(pszArgs); … … 913 1017 pThis->u8State & AUX_STATE_ENABLED ? "enabled" : "disabled"); 914 1018 pHlp->pfnPrintf(pHlp, "Protocol: %s, scaling %u:1\n", 915 pcszProtocols[pThis->enmProtocol], pThis->u8State & AUX_STATE_SCALING ? 2 : 1); 1019 pcszProtocols[pThis->enmProtocol], 1020 pThis->u8State & AUX_STATE_SCALING ? 2 : 1); 916 1021 pHlp->pfnPrintf(pHlp, "Active command %02X\n", pThis->u8CurrCmd); 917 1022 pHlp->pfnPrintf(pHlp, "Sampling rate %u reports/sec, resolution %u counts/mm\n", … … 953 1058 int32_t dz, int32_t dw, uint32_t fButtons) 954 1059 { 955 RT_NOREF1(dw);956 1060 int rc = VINF_SUCCESS; 957 1061 958 /* Update internal accumulators and button state. */1062 /* Update internal accumulators and button state. Ignore any buttons beyond 5. */ 959 1063 pThis->iAccumX += dx; 960 1064 pThis->iAccumY += dy; 961 1065 pThis->iAccumZ += dz; 962 pThis->fAccumB |= fButtons; /// @todo accumulate based on current protocol? 963 pThis->fCurrB = fButtons; 964 965 /* Report the event and start the throttle timer unless it's already running. */ 966 if (!pThis->fThrottleActive) 1066 pThis->iAccumW += dw; 1067 pThis->fCurrB = fButtons & (PS2M_STD_BTN_MASK | PS2M_IMEX_BTN_MASK); 1068 pThis->fAccumB |= pThis->fCurrB; 1069 1070 /* Ditch accumulated data that can't be reported by the current protocol. 1071 * This avoids sending phantom empty reports when un-reportable events 1072 * are received. 1073 */ 1074 if (pThis->enmProtocol < PS2M_PROTO_IMEX_HORZ) 1075 pThis->iAccumW = 0; /* No horizontal scroll. */ 1076 1077 if (pThis->enmProtocol < PS2M_PROTO_IMEX) 1078 { 1079 pThis->fAccumB &= PS2M_STD_BTN_MASK; /* Only buttons 1-3. */ 1080 pThis->fCurrB &= PS2M_STD_BTN_MASK; 1081 } 1082 1083 if (pThis->enmProtocol < PS2M_PROTO_IMPS2) 1084 pThis->iAccumZ = 0; /* No vertical scroll. */ 1085 1086 /* Report the event (if any) and start the throttle timer unless it's already running. */ 1087 if (!pThis->fThrottleActive && ps2mHaveEvents(pThis)) 967 1088 { 968 1089 ps2mReportAccumulatedEvents(pThis, (GeneriQ *)&pThis->evtQ, true);
Note:
See TracChangeset
for help on using the changeset viewer.