Changeset 77323 in vbox for trunk/src/VBox/Runtime/r3
- Timestamp:
- Feb 14, 2019 9:20:55 PM (6 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Runtime/r3/win/serialport-win.cpp
r76553 r77323 76 76 /** Events currently waited for. */ 77 77 uint32_t fEvtMask; 78 /** Event mask as received by WaitCommEvent(). */ 79 DWORD dwEventMask; 78 80 /** Flag whether a write is currently pending. */ 79 81 bool fWritePending; 82 /** Event query pending. */ 83 bool fEvtQueryPending; 80 84 /** Bounce buffer for writes. */ 81 85 uint8_t *pbBounceBuf; … … 247 251 248 252 253 /** 254 * Processes the received Windows comm events and converts them to our format. 255 * 256 * @returns IPRT status code. 257 * @param pThis The pipe instance handle. 258 * @param dwEventMask Event mask received. 259 * @param pfEvtsRecv Where to store the converted events. 260 */ 261 static int rtSerialPortEvtFlagsProcess(PRTSERIALPORTINTERNAL pThis, DWORD dwEventMask, uint32_t *pfEvtsRecv) 262 { 263 int rc = VINF_SUCCESS; 264 265 if (dwEventMask & EV_RXCHAR) 266 *pfEvtsRecv |= RTSERIALPORT_EVT_F_DATA_RX; 267 if (dwEventMask & EV_TXEMPTY) 268 { 269 if (pThis->fWritePending) 270 { 271 rc = rtSerialPortWriteCheckCompletion(pThis); 272 if (rc == VINF_SUCCESS) 273 *pfEvtsRecv |= RTSERIALPORT_EVT_F_DATA_TX; 274 else 275 rc = VINF_SUCCESS; 276 } 277 else 278 *pfEvtsRecv |= RTSERIALPORT_EVT_F_DATA_TX; 279 } 280 if (dwEventMask & EV_BREAK) 281 *pfEvtsRecv |= RTSERIALPORT_EVT_F_BREAK_DETECTED; 282 if (dwEventMask & (EV_CTS | EV_DSR | EV_RING | EV_RLSD)) 283 *pfEvtsRecv |= RTSERIALPORT_EVT_F_STATUS_LINE_CHANGED; 284 285 return rc; 286 } 287 288 289 /** 290 * The internal comm event wait worker. 291 * 292 * @returns IPRT status code. 293 * @param pThis The pipe instance handle. 294 * @param msTimeout The timeout to wait for. 295 */ 296 static int rtSerialPortEvtWaitWorker(PRTSERIALPORTINTERNAL pThis, RTMSINTERVAL msTimeout) 297 { 298 int rc = VINF_SUCCESS; 299 HANDLE ahWait[2]; 300 ahWait[0] = pThis->hEvtDev; 301 ahWait[1] = pThis->hEvtIntr; 302 303 DWORD dwRet = WaitForMultipleObjects(2, ahWait, FALSE, msTimeout == RT_INDEFINITE_WAIT ? INFINITE : msTimeout); 304 if (dwRet == WAIT_TIMEOUT) 305 rc = VERR_TIMEOUT; 306 else if (dwRet == WAIT_FAILED) 307 rc = RTErrConvertFromWin32(GetLastError()); 308 else if (dwRet == WAIT_OBJECT_0) 309 rc = VINF_SUCCESS; 310 else 311 { 312 Assert(dwRet == WAIT_OBJECT_0 + 1); 313 rc = VERR_INTERRUPTED; 314 } 315 316 return rc; 317 } 318 319 249 320 RTDECL(int) RTSerialPortOpen(PRTSERIALPORT phSerialPort, const char *pszPortAddress, uint32_t fFlags) 250 321 { … … 263 334 pThis->fEvtMask = 0; 264 335 pThis->fWritePending = false; 336 pThis->fEvtQueryPending = false; 265 337 pThis->pbBounceBuf = NULL; 266 338 pThis->cbBounceBufUsed = 0; … … 786 858 int rc = VINF_SUCCESS; 787 859 if (fEvtMask != pThis->fEvtMask) 860 { 788 861 rc = rtSerialPortWinUpdateEvtMask(pThis, fEvtMask); 862 if ( RT_SUCCESS(rc) 863 && pThis->fEvtQueryPending) 864 { 865 /* 866 * Setting a new event mask lets the WaitCommEvent() call finish immediately, 867 * so clean up and process any events here. 868 */ 869 rc = rtSerialPortEvtWaitWorker(pThis, 1); 870 AssertRC(rc); 871 872 if (pThis->dwEventMask != 0) 873 { 874 pThis->fEvtQueryPending = false; 875 return rtSerialPortEvtFlagsProcess(pThis, pThis->dwEventMask, pfEvtsRecv); 876 } 877 } 878 } 789 879 790 880 /* … … 817 907 if (RT_SUCCESS(rc)) 818 908 { 819 DWORD dwEventMask = 0; 820 HANDLE ahWait[2]; 821 ahWait[0] = pThis->hEvtDev; 822 ahWait[1] = pThis->hEvtIntr; 823 824 RT_ZERO(pThis->OverlappedEvt); 825 pThis->OverlappedEvt.hEvent = pThis->hEvtDev; 826 827 if (!WaitCommEvent(pThis->hDev, &dwEventMask, &pThis->OverlappedEvt)) 828 { 829 DWORD dwRet = GetLastError(); 830 if (dwRet == ERROR_IO_PENDING) 831 { 832 dwRet = WaitForMultipleObjects(2, ahWait, FALSE, msTimeout == RT_INDEFINITE_WAIT ? INFINITE : msTimeout); 833 if (dwRet == WAIT_TIMEOUT) 834 rc = VERR_TIMEOUT; 835 else if (dwRet == WAIT_FAILED) 909 /* Set up a new event wait if there is none pending. */ 910 if (!pThis->fEvtQueryPending) 911 { 912 RT_ZERO(pThis->OverlappedEvt); 913 pThis->OverlappedEvt.hEvent = pThis->hEvtDev; 914 915 pThis->dwEventMask = 0; 916 pThis->fEvtQueryPending = true; 917 if (!WaitCommEvent(pThis->hDev, &pThis->dwEventMask, &pThis->OverlappedEvt)) 918 { 919 DWORD dwRet = GetLastError(); 920 if (dwRet == ERROR_IO_PENDING) 921 rc = VINF_SUCCESS; 922 else 836 923 rc = RTErrConvertFromWin32(GetLastError()); 837 else if (dwRet != WAIT_OBJECT_0)838 rc = VERR_INTERRUPTED;839 924 } 840 925 else 841 rc = RTErrConvertFromWin32(dwRet); 842 } 926 pThis->fEvtQueryPending = false; 927 } 928 929 Assert(RT_FAILURE(rc) || pThis->fEvtQueryPending); 930 931 if ( RT_SUCCESS(rc) 932 || pThis->fEvtQueryPending) 933 rc = rtSerialPortEvtWaitWorker(pThis, msTimeout); 843 934 844 935 if (RT_SUCCESS(rc)) 845 936 { 846 /* Check the event */ 847 if (dwEventMask & EV_RXCHAR) 848 *pfEvtsRecv |= RTSERIALPORT_EVT_F_DATA_RX; 849 if (dwEventMask & EV_TXEMPTY) 850 { 851 if (pThis->fWritePending) 852 { 853 rc = rtSerialPortWriteCheckCompletion(pThis); 854 if (rc == VINF_SUCCESS) 855 *pfEvtsRecv |= RTSERIALPORT_EVT_F_DATA_TX; 856 else 857 rc = VINF_SUCCESS; 858 } 859 else 860 *pfEvtsRecv |= RTSERIALPORT_EVT_F_DATA_TX; 861 } 862 if (dwEventMask & EV_BREAK) 863 *pfEvtsRecv |= RTSERIALPORT_EVT_F_BREAK_DETECTED; 864 if (dwEventMask & (EV_CTS | EV_DSR | EV_RING | EV_RLSD)) 865 *pfEvtsRecv |= RTSERIALPORT_EVT_F_STATUS_LINE_CHANGED; 937 pThis->fEvtQueryPending = false; 938 rc = rtSerialPortEvtFlagsProcess(pThis, pThis->dwEventMask, pfEvtsRecv); 866 939 } 867 940 }
Note:
See TracChangeset
for help on using the changeset viewer.