- Timestamp:
- Jun 14, 2022 11:14:07 AM (3 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Devices/Input/UsbMouse.cpp
r95272 r95275 242 242 bool fTouchReporting; 243 243 bool fTouchStateUpdated; 244 245 struct246 {247 MTCONTACT aCurrentContactState[TPAD_CONTACT_MAX_COUNT];248 MTCONTACT aReportingContactState[TPAD_CONTACT_MAX_COUNT];249 uint32_t u32LastTouchScanTime;250 bool fTouchReporting;251 bool fTouchStateUpdated;252 } tpad;253 244 } USBHID; 254 245 /** Pointer to the USB HID instance data. */ … … 318 309 /** 319 310 * The USB HID report structure for the touchpad device. 311 * It is a superset of the multi-touch report. 320 312 */ 321 313 typedef struct USBHIDTP_REPORT 322 314 { 323 uint8_t idReport; 324 uint8_t cContacts; 325 struct 326 { 327 uint8_t fContact; 328 uint8_t cContact; 329 uint16_t x; 330 uint16_t y; 331 } aContacts[MT_CONTACTS_PER_REPORT]; 332 uint32_t u32ScanTime; 333 uint8_t buttons; 315 USBHIDMT_REPORT mt; 316 uint8_t buttons; /* Required by Win10, not used. */ 334 317 } USBHIDTP_REPORT, *PUSBHIDTP_REPORT; 335 318 … … 1519 1502 pThis->fHasPendingChanges = false; 1520 1503 pThis->fTouchStateUpdated = false; 1521 pThis->tpad.fTouchStateUpdated = false;1522 1504 1523 1505 for (unsigned i = 0; i < RT_ELEMENTS(pThis->aEps); i++) … … 1624 1606 uint8_t cContacts = 0; 1625 1607 1608 uint8_t cMaxContacts = pThis->enmMode == USBHIDMODE_MT_RELATIVE ? TPAD_CONTACT_MAX_COUNT : MT_CONTACT_MAX_COUNT; 1609 size_t cbReport = pThis->enmMode == USBHIDMODE_MT_RELATIVE ? sizeof(USBHIDTP_REPORT) : sizeof(USBHIDMT_REPORT); 1610 1626 1611 Assert(pThis->fHasPendingChanges); 1627 1612 … … 1635 1620 * that is they must be reported to the guest. 1636 1621 */ 1637 for (i = 0; i < MT_CONTACT_MAX_COUNT; i++)1622 for (i = 0; i < cMaxContacts; i++) 1638 1623 { 1639 1624 pRepContact = &pThis->aReportingContactState[i]; … … 1686 1671 1687 1672 /* Report current state. */ 1688 USBHID MT_REPORT r;1689 USBHID MT_REPORT *p = &r;1673 USBHIDTP_REPORT r; 1674 USBHIDTP_REPORT *p = &r; 1690 1675 RT_ZERO(*p); 1691 1676 1692 p->idReport = REPORTID_TOUCH_EVENT; 1693 p->cContacts = cContacts; 1677 p->mt.idReport = REPORTID_TOUCH_EVENT; 1678 p->mt.cContacts = cContacts; 1679 p->buttons = 0; /* Not currently used. */ 1694 1680 1695 1681 uint8_t iReportedContact; … … 1719 1705 } 1720 1706 1721 p->aContacts[iReportedContact].fContact = pRepContact->flags; 1722 p->aContacts[iReportedContact].cContact = pRepContact->id; 1723 p->aContacts[iReportedContact].x = pRepContact->x >> pThis->u8CoordShift; 1724 p->aContacts[iReportedContact].y = pRepContact->y >> pThis->u8CoordShift; 1725 } 1726 1727 p->u32ScanTime = pThis->u32LastTouchScanTime * 10; 1707 p->mt.aContacts[iReportedContact].fContact = pRepContact->flags; 1708 p->mt.aContacts[iReportedContact].cContact = pRepContact->id; 1709 p->mt.aContacts[iReportedContact].x = pRepContact->x >> pThis->u8CoordShift; 1710 p->mt.aContacts[iReportedContact].y = pRepContact->y >> pThis->u8CoordShift; 1711 1712 if (pThis->enmMode == USBHIDMODE_MT_RELATIVE) { 1713 /** @todo Parse touch confidence in Qt frontend */ 1714 p->mt.aContacts[iReportedContact].fContact |= MT_CONTACT_F_CONFIDENCE; 1715 } 1716 } 1717 1718 p->mt.u32ScanTime = pThis->u32LastTouchScanTime * 10; 1728 1719 1729 1720 Assert(iReportedContact > 0); … … 1744 1735 } 1745 1736 1746 LogRel3(("usbHid: reporting touch contact:\n%.*Rhxd\n", sizeof(USBHIDMT_REPORT), p)); 1747 return usbHidCompleteOk(pThis, pUrb, p, sizeof(USBHIDMT_REPORT)); 1748 } 1749 1750 1751 static int usbHidSendTouchPadReport(PUSBHID pThis, PVUSBURB pUrb) 1752 { 1753 uint8_t i; 1754 MTCONTACT *pRepContact; 1755 MTCONTACT *pCurContact; 1756 1757 /* Number of contacts to be reported. In hybrid mode the first report contains 1758 * total number of contacts and subsequent reports contain 0. 1759 */ 1760 uint8_t cContacts = 0; 1761 1762 Assert(pThis->fHasPendingChanges); 1763 1764 if (!pThis->tpad.fTouchReporting) 1765 { 1766 pThis->tpad.fTouchReporting = true; 1767 pThis->tpad.fTouchStateUpdated = false; 1768 1769 /* Update the reporting state with the new current state. 1770 * Also mark all active contacts in reporting state as dirty, 1771 * that is they must be reported to the guest. 1772 */ 1773 for (i = 0; i < TPAD_CONTACT_MAX_COUNT; i++) 1774 { 1775 pRepContact = &pThis->tpad.aReportingContactState[i]; 1776 pCurContact = &pThis->tpad.aCurrentContactState[i]; 1777 1778 if (pCurContact->status & MT_CONTACT_S_ACTIVE) 1779 { 1780 if (pCurContact->status & MT_CONTACT_S_REUSED) 1781 { 1782 pCurContact->status &= ~MT_CONTACT_S_REUSED; 1783 1784 /* Keep x,y. Will report lost contact at this point. */ 1785 pRepContact->id = pCurContact->oldId; 1786 pRepContact->flags = 0; 1787 pRepContact->status = MT_CONTACT_S_REUSED; 1788 } 1789 else if (pThis->tpad.aCurrentContactState[i].status & MT_CONTACT_S_CANCELLED) 1790 { 1791 pCurContact->status &= ~(MT_CONTACT_S_CANCELLED | MT_CONTACT_S_ACTIVE); 1792 1793 /* Keep x,y. Will report lost contact at this point. */ 1794 pRepContact->id = pCurContact->id; 1795 pRepContact->flags = 0; 1796 pRepContact->status = 0; 1797 } 1798 else 1799 { 1800 if (pCurContact->flags == 0) 1801 { 1802 pCurContact->status &= ~MT_CONTACT_S_ACTIVE; /* Contact disapeared. */ 1803 } 1804 1805 pRepContact->x = pCurContact->x; 1806 pRepContact->y = pCurContact->y; 1807 pRepContact->id = pCurContact->id; 1808 pRepContact->flags = pCurContact->flags; 1809 pRepContact->status = 0; 1810 } 1811 1812 cContacts++; 1813 1814 pRepContact->status |= MT_CONTACT_S_DIRTY; 1815 } 1816 else 1817 { 1818 pRepContact->status = 0; 1819 } 1820 } 1821 } 1822 1823 /* Report current state. */ 1824 USBHIDTP_REPORT r; 1825 USBHIDTP_REPORT *p = &r; 1826 RT_ZERO(*p); 1827 1828 p->idReport = REPORTID_TOUCH_EVENT; 1829 p->cContacts = cContacts; 1830 p->buttons = 0; 1831 1832 uint8_t iReportedContact; 1833 for (iReportedContact = 0; iReportedContact < MT_CONTACTS_PER_REPORT; iReportedContact++) 1834 { 1835 /* Find the next not reported contact. */ 1836 pRepContact = usbHidFindMTContact(pThis->tpad.aReportingContactState, RT_ELEMENTS(pThis->tpad.aReportingContactState), 1837 MT_CONTACT_S_DIRTY, MT_CONTACT_S_DIRTY); 1838 1839 if (!pRepContact) 1840 { 1841 LogRel3(("usbHid: no more touch contacts to report\n")); 1842 break; 1843 } 1844 1845 if (pRepContact->status & MT_CONTACT_S_REUSED) 1846 { 1847 /* Do not clear DIRTY flag for contacts which were reused. 1848 * Because two reports must be generated: 1849 * one for old contact off, and the second for new contact on. 1850 */ 1851 pRepContact->status &= ~MT_CONTACT_S_REUSED; 1852 } 1853 else 1854 { 1855 pRepContact->status &= ~MT_CONTACT_S_DIRTY; 1856 } 1857 1858 /** @todo Parse touch confidence in Qt frontend */ 1859 p->aContacts[iReportedContact].fContact = pRepContact->flags | MT_CONTACT_F_CONFIDENCE; 1860 p->aContacts[iReportedContact].cContact = pRepContact->id; 1861 p->aContacts[iReportedContact].x = pRepContact->x >> pThis->u8CoordShift; 1862 p->aContacts[iReportedContact].y = pRepContact->y >> pThis->u8CoordShift; 1863 } 1864 1865 p->u32ScanTime = pThis->tpad.u32LastTouchScanTime * 10; 1866 1867 Assert(iReportedContact > 0); 1868 1869 /* Reset TouchReporting if all contacts reported. */ 1870 pRepContact = usbHidFindMTContact(pThis->tpad.aReportingContactState, RT_ELEMENTS(pThis->tpad.aReportingContactState), 1871 MT_CONTACT_S_DIRTY, MT_CONTACT_S_DIRTY); 1872 1873 if (!pRepContact) 1874 { 1875 LogRel3(("usbHid: all touch contacts reported\n")); 1876 pThis->tpad.fTouchReporting = false; 1877 pThis->fHasPendingChanges = pThis->tpad.fTouchStateUpdated; 1878 } 1879 else 1880 { 1881 pThis->fHasPendingChanges = true; 1882 } 1883 1884 LogRel3(("usbHid: reporting touch contact:\n%.*Rhxd\n", sizeof(USBHIDTP_REPORT), p)); 1885 return usbHidCompleteOk(pThis, pUrb, p, sizeof(USBHIDTP_REPORT)); 1886 } 1737 LogRel3(("usbHid: reporting touch contact:\n%.*Rhxd\n", cbReport, p)); 1738 return usbHidCompleteOk(pThis, pUrb, p, cbReport); 1739 } 1740 1887 1741 1888 1742 /** … … 1893 1747 PVUSBURB pUrb = usbHidQueueRemoveHead(&pThis->ToHostQueue); 1894 1748 1895 if (pThis->enmMode == USBHIDMODE_MT_ABSOLUTE )1896 { 1897 /* Th is device uses a different reporting method and fHasPendingChanges maintenance. */1749 if (pThis->enmMode == USBHIDMODE_MT_ABSOLUTE || pThis->enmMode == USBHIDMODE_MT_RELATIVE) 1750 { 1751 /* These modes use a different reporting method and maintain fHasPendingChanges. */ 1898 1752 if (pUrb) 1899 1753 return usbHidSendMultiTouchReport(pThis, pUrb); 1900 return VINF_SUCCESS;1901 }1902 if (pThis->enmMode == USBHIDMODE_MT_RELATIVE)1903 {1904 /* This device uses a different reporting method and fHasPendingChanges maintenance. */1905 if (pUrb)1906 return usbHidSendTouchPadReport(pThis, pUrb);1907 1754 return VINF_SUCCESS; 1908 1755 } … … 1996 1843 * @interface_method_impl{PDMIMOUSEPORT,pfnPutEventTouchScreen} 1997 1844 */ 1998 static DECLCALLBACK(int) usbHidMousePutEvent TouchScreen(PPDMIMOUSEPORT pInterface,1845 static DECLCALLBACK(int) usbHidMousePutEventMultiTouch(PUSBHID pThis, 1999 1846 uint8_t cContacts, 2000 1847 const uint64_t *pau64Contacts, … … 2016 1863 paNewContacts[i].y = (uint16_t)(u32Lo >> 16); 2017 1864 paNewContacts[i].id = RT_BYTE1(u32Hi); 2018 paNewContacts[i].flags = RT_BYTE2(u32Hi) & (MT_CONTACT_F_IN_CONTACT | MT_CONTACT_F_IN_RANGE);1865 paNewContacts[i].flags = RT_BYTE2(u32Hi); 2019 1866 paNewContacts[i].status = MT_CONTACT_S_DIRTY; 2020 1867 paNewContacts[i].oldId = 0; /* Not used. */ 2021 if (paNewContacts[i].flags & MT_CONTACT_F_IN_CONTACT) 1868 1869 if (pThis->enmMode == USBHIDMODE_MT_ABSOLUTE) 2022 1870 { 2023 paNewContacts[i].flags |= MT_CONTACT_F_IN_RANGE; 1871 paNewContacts[i].flags &= MT_CONTACT_F_IN_CONTACT | MT_CONTACT_F_IN_RANGE; 1872 if (paNewContacts[i].flags & MT_CONTACT_F_IN_CONTACT) 1873 { 1874 paNewContacts[i].flags |= MT_CONTACT_F_IN_RANGE; 1875 } 2024 1876 } 2025 } 2026 2027 PUSBHID pThis = RT_FROM_MEMBER(pInterface, USBHID, Lun0.IPort); 1877 else 1878 { 1879 Assert(pThis->enmMode == USBHIDMODE_MT_RELATIVE); 1880 paNewContacts[i].flags &= MT_CONTACT_F_IN_CONTACT; 1881 } 1882 } 1883 2028 1884 MTCONTACT *pCurContact = NULL; 2029 1885 MTCONTACT *pNewContact = NULL; 2030 1886 2031 1887 RTCritSectEnter(&pThis->CritSect); 2032 2033 Assert(pThis->enmMode == USBHIDMODE_MT_ABSOLUTE);2034 1888 2035 1889 /* Maintain a state of all current contacts. … … 2167 2021 2168 2022 /** 2023 * @interface_method_impl{PDMIMOUSEPORT,pfnPutEventTouchScreen} 2024 */ 2025 static DECLCALLBACK(int) usbHidMousePutEventTouchScreen(PPDMIMOUSEPORT pInterface, 2026 uint8_t cContacts, 2027 const uint64_t *pau64Contacts, 2028 uint32_t u32ScanTime) 2029 { 2030 PUSBHID pThis = RT_FROM_MEMBER(pInterface, USBHID, Lun0.IPort); 2031 2032 Assert(pThis->enmMode == USBHIDMODE_MT_ABSOLUTE); 2033 2034 return usbHidMousePutEventMultiTouch(pThis, cContacts, pau64Contacts, u32ScanTime); 2035 } 2036 2037 /** 2169 2038 * @interface_method_impl{PDMIMOUSEPORT,pfnPutEventTouchPad} 2170 2039 */ … … 2174 2043 uint32_t u32ScanTime) 2175 2044 { 2176 uint8_t i;2177 uint8_t j;2178 2179 /* Make a copy of new contacts */2180 MTCONTACT *paNewContacts = (MTCONTACT *)RTMemTmpAlloc(sizeof(MTCONTACT) * cContacts);2181 if (!paNewContacts)2182 return VERR_NO_MEMORY;2183 2184 for (i = 0; i < cContacts; i++)2185 {2186 uint32_t u32Lo = RT_LO_U32(pau64Contacts[i]);2187 uint32_t u32Hi = RT_HI_U32(pau64Contacts[i]);2188 paNewContacts[i].x = (uint16_t)u32Lo;2189 paNewContacts[i].y = (uint16_t)(u32Lo >> 16);2190 paNewContacts[i].id = RT_BYTE1(u32Hi);2191 paNewContacts[i].flags = RT_BYTE2(u32Hi) & MT_CONTACT_F_IN_CONTACT;2192 paNewContacts[i].status = MT_CONTACT_S_DIRTY;2193 paNewContacts[i].oldId = 0; /* Not used. */2194 }2195 2196 2045 PUSBHID pThis = RT_FROM_MEMBER(pInterface, USBHID, Lun0.IPort); 2197 MTCONTACT *pCurContact = NULL;2198 MTCONTACT *pNewContact = NULL;2199 2200 RTCritSectEnter(&pThis->CritSect);2201 2046 2202 2047 Assert(pThis->enmMode == USBHIDMODE_MT_RELATIVE); 2203 2048 2204 /* Maintain a state of all current contacts. 2205 * Intr URBs will be completed according to the state. 2206 */ 2207 2208 /* Mark all existing contacts as dirty. */ 2209 for (i = 0; i < RT_ELEMENTS(pThis->tpad.aCurrentContactState); i++) 2210 pThis->tpad.aCurrentContactState[i].status |= MT_CONTACT_S_DIRTY; 2211 2212 /* Update existing contacts and mark new contacts. */ 2213 for (i = 0; i < cContacts; i++) 2214 { 2215 pNewContact = &paNewContacts[i]; 2216 2217 /* Find existing contact with the same id. */ 2218 pCurContact = NULL; 2219 for (j = 0; j < RT_ELEMENTS(pThis->tpad.aCurrentContactState); j++) 2220 { 2221 if ( (pThis->tpad.aCurrentContactState[j].status & MT_CONTACT_S_ACTIVE) != 0 2222 && pThis->tpad.aCurrentContactState[j].id == pNewContact->id) 2223 { 2224 pCurContact = &pThis->tpad.aCurrentContactState[j]; 2225 break; 2226 } 2227 } 2228 2229 if (pCurContact) 2230 { 2231 pNewContact->status &= ~MT_CONTACT_S_DIRTY; 2232 2233 pCurContact->x = pNewContact->x; 2234 pCurContact->y = pNewContact->y; 2235 if (pCurContact->flags == 0) /* Contact disappeared already. */ 2236 { 2237 if ((pCurContact->status & MT_CONTACT_S_REUSED) == 0) 2238 { 2239 pCurContact->status |= MT_CONTACT_S_REUSED; /* Report to the guest that the contact not in touch. */ 2240 pCurContact->oldId = pCurContact->id; 2241 } 2242 } 2243 pCurContact->flags = pNewContact->flags; 2244 pCurContact->status &= ~MT_CONTACT_S_DIRTY; 2245 } 2246 } 2247 2248 /* Append new contacts (the dirty one in the paNewContacts). */ 2249 for (i = 0; i < cContacts; i++) 2250 { 2251 pNewContact = &paNewContacts[i]; 2252 2253 if (pNewContact->status & MT_CONTACT_S_DIRTY) 2254 { 2255 /* It is a new contact, copy is to one of not ACTIVE or not updated existing contacts. */ 2256 pCurContact = usbHidFindMTContact(pThis->tpad.aCurrentContactState, RT_ELEMENTS(pThis->tpad.aCurrentContactState), 2257 MT_CONTACT_S_ACTIVE, 0); 2258 2259 if (pCurContact) 2260 { 2261 *pCurContact = *pNewContact; 2262 pCurContact->status = MT_CONTACT_S_ACTIVE; /* Reset status. */ 2263 } 2264 else 2265 { 2266 /* Dirty existing contacts can be reused. */ 2267 pCurContact = usbHidFindMTContact(pThis->tpad.aCurrentContactState, RT_ELEMENTS(pThis->tpad.aCurrentContactState), 2268 MT_CONTACT_S_ACTIVE | MT_CONTACT_S_DIRTY, 2269 MT_CONTACT_S_ACTIVE | MT_CONTACT_S_DIRTY); 2270 2271 if (pCurContact) 2272 { 2273 pCurContact->x = pNewContact->x; 2274 pCurContact->y = pNewContact->y; 2275 if ((pCurContact->status & MT_CONTACT_S_REUSED) == 0) 2276 { 2277 pCurContact->status |= MT_CONTACT_S_REUSED; /* Report to the guest that the contact not in touch. */ 2278 pCurContact->oldId = pCurContact->id; 2279 } 2280 pCurContact->flags = pNewContact->flags; 2281 pCurContact->status &= ~MT_CONTACT_S_DIRTY; 2282 } 2283 else 2284 { 2285 LogRel3(("usbHid: dropped new contact: %d,%d id %d flags %RX8 status %RX8 oldId %d\n", 2286 pNewContact->x, 2287 pNewContact->y, 2288 pNewContact->id, 2289 pNewContact->flags, 2290 pNewContact->status, 2291 pNewContact->oldId 2292 )); 2293 } 2294 } 2295 } 2296 } 2297 2298 /* Mark still dirty existing contacts as cancelled, because a new set of contacts does not include them. */ 2299 for (i = 0; i < RT_ELEMENTS(pThis->tpad.aCurrentContactState); i++) 2300 { 2301 pCurContact = &pThis->tpad.aCurrentContactState[i]; 2302 if (pCurContact->status & MT_CONTACT_S_DIRTY) 2303 { 2304 pCurContact->status |= MT_CONTACT_S_CANCELLED; 2305 pCurContact->status &= ~MT_CONTACT_S_DIRTY; 2306 } 2307 } 2308 2309 pThis->tpad.u32LastTouchScanTime = u32ScanTime; 2310 2311 LogRel3(("usbHid: scanTime (ms): %d\n", pThis->tpad.u32LastTouchScanTime)); 2312 for (i = 0; i < RT_ELEMENTS(pThis->tpad.aCurrentContactState); i++) 2313 { 2314 LogRel3(("usbHid: contact state[%d]: %d,%d id %d flags %RX8 status %RX8 oldId %d\n", 2315 i, 2316 pThis->tpad.aCurrentContactState[i].x, 2317 pThis->tpad.aCurrentContactState[i].y, 2318 pThis->tpad.aCurrentContactState[i].id, 2319 pThis->tpad.aCurrentContactState[i].flags, 2320 pThis->tpad.aCurrentContactState[i].status, 2321 pThis->tpad.aCurrentContactState[i].oldId 2322 )); 2323 } 2324 2325 pThis->tpad.fTouchStateUpdated = true; 2326 pThis->fHasPendingChanges = true; 2327 2328 /* Send a report if possible. */ 2329 usbHidSendReport(pThis); 2330 2331 RTCritSectLeave(&pThis->CritSect); 2332 2333 RTMemTmpFree(paNewContacts); 2334 return VINF_SUCCESS; 2049 return usbHidMousePutEventMultiTouch(pThis, cContacts, pau64Contacts, u32ScanTime); 2335 2050 } 2336 2051 … … 2561 2276 /* The actual state should be reported here. */ 2562 2277 RT_ZERO(*p); 2563 p-> idReport = REPORTID_TOUCH_EVENT;2278 p->mt.idReport = REPORTID_TOUCH_EVENT; 2564 2279 cbData = sizeof(USBHIDTP_REPORT); 2565 2280 break;
Note:
See TracChangeset
for help on using the changeset viewer.