Changeset 71028 in vbox for trunk/src/VBox/Runtime/r3
- Timestamp:
- Feb 15, 2018 3:28:14 PM (7 years ago)
- Location:
- trunk/src/VBox/Runtime/r3
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Runtime/r3/posix/serialport-posix.cpp
r70760 r71028 104 104 /** Event pending mask. */ 105 105 volatile uint32_t fEvtsPending; 106 /** Flag whether we are in blocking or non blocking mode. */ 107 bool fBlocking; 106 108 /** The current active config (we assume no one changes this behind our back). */ 107 109 struct termios PortCfg; … … 634 636 635 637 638 /** 639 * The slow path of rtSerialPortSwitchBlockingMode that does the actual switching. 640 * 641 * @returns IPRT status code. 642 * @param pThis The internal serial port instance data. 643 * @param fBlocking The desired mode of operation. 644 * @remarks Do not call directly. 645 */ 646 static int rtSerialPortSwitchBlockingModeSlow(PRTSERIALPORTINTERNAL pThis, bool fBlocking) 647 { 648 int fFlags = fcntl(pThis->iFd, F_GETFL, 0); 649 if (fFlags == -1) 650 return RTErrConvertFromErrno(errno); 651 652 if (fBlocking) 653 fFlags &= ~O_NONBLOCK; 654 else 655 fFlags |= O_NONBLOCK; 656 if (fcntl(pThis->iFd, F_SETFL, fFlags) == -1) 657 return RTErrConvertFromErrno(errno); 658 659 pThis->fBlocking = fBlocking; 660 return VINF_SUCCESS; 661 } 662 663 664 /** 665 * Switches the serial port to the desired blocking mode if necessary. 666 * 667 * @returns IPRT status code. 668 * @param pThis The internal serial port instance data. 669 * @param fBlocking The desired mode of operation. 670 */ 671 DECLINLINE(int) rtSerialPortSwitchBlockingMode(PRTSERIALPORTINTERNAL pThis, bool fBlocking) 672 { 673 if (pThis->fBlocking != fBlocking) 674 return rtSerialPortSwitchBlockingModeSlow(pThis, fBlocking); 675 return VINF_SUCCESS; 676 } 677 678 636 679 RTDECL(int) RTSerialPortOpen(PRTSERIALPORT phSerialPort, const char *pszPortAddress, uint32_t fFlags) 637 680 { … … 659 702 pThis->fEvtsPending = 0; 660 703 pThis->iFd = open(pszPortAddress, fPsxFlags); 704 pThis->fBlocking = false; 661 705 if (pThis->iFd != -1) 662 706 { … … 747 791 RTDECL(int) RTSerialPortRead(RTSERIALPORT hSerialPort, void *pvBuf, size_t cbToRead, size_t *pcbRead) 748 792 { 749 RT_NOREF(hSerialPort, pvBuf, cbToRead, pcbRead); 750 return VERR_NOT_IMPLEMENTED; 793 PRTSERIALPORTINTERNAL pThis = hSerialPort; 794 AssertPtrReturn(pThis, VERR_INVALID_PARAMETER); 795 AssertReturn(pThis->u32Magic == RTSERIALPORT_MAGIC, VERR_INVALID_HANDLE); 796 AssertPtrReturn(pvBuf, VERR_INVALID_POINTER); 797 AssertReturn(cbToRead > 0, VERR_INVALID_PARAMETER); 798 799 int rc = rtSerialPortSwitchBlockingMode(pThis, true); 800 if (RT_SUCCESS(rc)) 801 { 802 /* 803 * Attempt read. 804 */ 805 ssize_t cbRead = read(pThis->iFd, pvBuf, cbToRead); 806 if (cbRead >= 0) 807 { 808 if (pcbRead) 809 /* caller can handle partial read. */ 810 *pcbRead = cbRead; 811 else 812 { 813 /* Caller expects all to be read. */ 814 while ((ssize_t)cbToRead > cbRead) 815 { 816 ssize_t cbReadPart = read(pThis->iFd, (uint8_t *)pvBuf + cbRead, cbToRead - cbRead); 817 if (cbReadPart < 0) 818 return RTErrConvertFromErrno(errno); 819 820 cbRead += cbReadPart; 821 } 822 } 823 } 824 else 825 rc = RTErrConvertFromErrno(errno); 826 } 827 828 return rc; 751 829 } 752 830 … … 763 841 *pcbRead = 0; 764 842 765 int rc = VINF_SUCCESS; 766 ssize_t cbThisRead = read(pThis->iFd, pvBuf, cbToRead); 767 if (cbThisRead > 0) 843 int rc = rtSerialPortSwitchBlockingMode(pThis, false); 844 if (RT_SUCCESS(rc)) 845 { 846 ssize_t cbThisRead = read(pThis->iFd, pvBuf, cbToRead); 847 if (cbThisRead > 0) 848 { 849 /* 850 * The read data needs to be scanned for the BREAK condition marker encoded in the data stream, 851 * if break detection was enabled during open. 852 */ 853 if (pThis->fOpenFlags & RTSERIALPORT_OPEN_F_DETECT_BREAK_CONDITION) 854 { /** @todo */ } 855 856 *pcbRead = cbThisRead; 857 } 858 else if (cbThisRead == 0 || errno == EAGAIN || errno == EWOULDBLOCK) 859 rc = VINF_TRY_AGAIN; 860 else 861 rc = RTErrConvertFromErrno(errno); 862 } 863 864 return rc; 865 } 866 867 868 RTDECL(int) RTSerialPortWrite(RTSERIALPORT hSerialPort, const void *pvBuf, size_t cbToWrite, size_t *pcbWritten) 869 { 870 PRTSERIALPORTINTERNAL pThis = hSerialPort; 871 AssertPtrReturn(pThis, VERR_INVALID_PARAMETER); 872 AssertReturn(pThis->u32Magic == RTSERIALPORT_MAGIC, VERR_INVALID_HANDLE); 873 AssertPtrReturn(pvBuf, VERR_INVALID_POINTER); 874 AssertReturn(cbToWrite > 0, VERR_INVALID_PARAMETER); 875 876 int rc = rtSerialPortSwitchBlockingMode(pThis, true); 877 if (RT_SUCCESS(rc)) 768 878 { 769 879 /* 770 * The read data needs to be scanned for the BREAK condition marker encoded in the data stream, 771 * if break detection was enabled during open. 880 * Attempt write. 772 881 */ 773 if (pThis->fOpenFlags & RTSERIALPORT_OPEN_F_DETECT_BREAK_CONDITION) 774 { /** @todo */ } 775 776 *pcbRead = cbThisRead; 777 } 778 else if (cbThisRead == 0 || errno == EAGAIN || errno == EWOULDBLOCK) 779 rc = VINF_TRY_AGAIN; 780 else 781 rc = RTErrConvertFromErrno(errno); 782 783 return rc; 784 } 785 786 787 RTDECL(int) RTSerialPortWrite(RTSERIALPORT hSerialPort, const void *pvBuf, size_t cbToWrite, size_t *pcbWritten) 788 { 789 RT_NOREF(hSerialPort, pvBuf, cbToWrite, pcbWritten); 790 return VERR_NOT_IMPLEMENTED; 882 ssize_t cbWritten = write(pThis->iFd, pvBuf, cbToWrite); 883 if (cbWritten >= 0) 884 { 885 if (pcbWritten) 886 /* caller can handle partial write. */ 887 *pcbWritten = cbWritten; 888 else 889 { 890 /* Caller expects all to be written. */ 891 while ((ssize_t)cbToWrite > cbWritten) 892 { 893 ssize_t cbWrittenPart = write(pThis->iFd, (const uint8_t *)pvBuf + cbWritten, cbToWrite - cbWritten); 894 if (cbWrittenPart < 0) 895 return RTErrConvertFromErrno(errno); 896 cbWritten += cbWrittenPart; 897 } 898 } 899 } 900 } 901 902 return rc; 791 903 } 792 904 … … 803 915 *pcbWritten = 0; 804 916 805 int rc = VINF_SUCCESS; 806 ssize_t cbThisWrite = write(pThis->iFd, pvBuf, cbToWrite); 807 if (cbThisWrite > 0) 808 *pcbWritten = cbThisWrite; 809 else if (cbThisWrite == 0 || errno == EAGAIN || errno == EWOULDBLOCK) 810 rc = VINF_TRY_AGAIN; 811 else 812 rc = RTErrConvertFromErrno(errno); 917 int rc = rtSerialPortSwitchBlockingMode(pThis, false); 918 if (RT_SUCCESS(rc)) 919 { 920 ssize_t cbThisWrite = write(pThis->iFd, pvBuf, cbToWrite); 921 if (cbThisWrite > 0) 922 *pcbWritten = cbThisWrite; 923 else if (cbThisWrite == 0 || errno == EAGAIN || errno == EWOULDBLOCK) 924 rc = VINF_TRY_AGAIN; 925 else 926 rc = RTErrConvertFromErrno(errno); 927 } 813 928 814 929 return rc; … … 892 1007 } 893 1008 894 struct pollfd aPollFds[2]; RT_ZERO(aPollFds); 895 aPollFds[0].fd = pThis->iFd; 896 aPollFds[0].events = POLLERR | POLLHUP; 897 aPollFds[0].revents = 0; 898 if ( (pThis->fOpenFlags & RTSERIALPORT_OPEN_F_READ) 899 && (fEvtMask & RTSERIALPORT_EVT_F_DATA_RX)) 900 aPollFds[0].events |= POLLIN; 901 if ( (pThis->fOpenFlags & RTSERIALPORT_OPEN_F_WRITE) 902 && (fEvtMask & RTSERIALPORT_EVT_F_DATA_TX)) 903 aPollFds[0].events |= POLLOUT; 904 905 aPollFds[1].fd = pThis->iFdPipeR; 906 aPollFds[1].events = POLLIN | POLLERR | POLLHUP; 907 aPollFds[1].revents = 0; 908 909 int rcPsx = 0; 910 int msTimeoutLeft = msTimeout == RT_INDEFINITE_WAIT ? -1 : msTimeout; 911 while (msTimeoutLeft != 0) 912 { 913 uint64_t tsPollStart = RTTimeMilliTS(); 914 915 rcPsx = poll(&aPollFds[0], RT_ELEMENTS(aPollFds), msTimeoutLeft); 916 if (rcPsx != -1 || errno != EINTR) 917 break; 918 /* Restart when getting interrupted. */ 919 if (msTimeoutLeft > -1) 920 { 921 uint64_t tsPollEnd = RTTimeMilliTS(); 922 uint64_t tsPollSpan = tsPollEnd - tsPollStart; 923 msTimeoutLeft -= RT_MIN(tsPollSpan, (uint32_t)msTimeoutLeft); 924 } 925 } 926 927 int rc = VINF_SUCCESS; 928 uint32_t fEvtsPending = 0; 929 if (rcPsx < 0 && errno != EINTR) 930 rc = RTErrConvertFromErrno(errno); 931 else if (rcPsx > 0) 932 { 933 if (aPollFds[0].revents != 0) 934 { 935 fEvtsPending |= (aPollFds[0].revents & POLLIN) ? RTSERIALPORT_EVT_F_DATA_RX : 0; 936 fEvtsPending |= (aPollFds[0].revents & POLLOUT) ? RTSERIALPORT_EVT_F_DATA_TX : 0; 937 /** @todo BREAK condition detection. */ 938 } 939 940 if (aPollFds[1].revents != 0) 941 { 942 AssertReturn(!(aPollFds[1].revents & (POLLHUP | POLLERR | POLLNVAL)), VERR_INTERNAL_ERROR); 943 Assert(aPollFds[1].revents & POLLIN); 944 945 uint8_t bWakeupReason = 0; 946 ssize_t cbRead = read(pThis->iFdPipeR, &bWakeupReason, 1); 947 if (cbRead == 1) 1009 int rc = rtSerialPortSwitchBlockingMode(pThis, false); 1010 if (RT_SUCCESS(rc)) 1011 { 1012 struct pollfd aPollFds[2]; RT_ZERO(aPollFds); 1013 aPollFds[0].fd = pThis->iFd; 1014 aPollFds[0].events = POLLERR | POLLHUP; 1015 aPollFds[0].revents = 0; 1016 if ( (pThis->fOpenFlags & RTSERIALPORT_OPEN_F_READ) 1017 && (fEvtMask & RTSERIALPORT_EVT_F_DATA_RX)) 1018 aPollFds[0].events |= POLLIN; 1019 if ( (pThis->fOpenFlags & RTSERIALPORT_OPEN_F_WRITE) 1020 && (fEvtMask & RTSERIALPORT_EVT_F_DATA_TX)) 1021 aPollFds[0].events |= POLLOUT; 1022 1023 aPollFds[1].fd = pThis->iFdPipeR; 1024 aPollFds[1].events = POLLIN | POLLERR | POLLHUP; 1025 aPollFds[1].revents = 0; 1026 1027 int rcPsx = 0; 1028 int msTimeoutLeft = msTimeout == RT_INDEFINITE_WAIT ? -1 : msTimeout; 1029 while (msTimeoutLeft != 0) 1030 { 1031 uint64_t tsPollStart = RTTimeMilliTS(); 1032 1033 rcPsx = poll(&aPollFds[0], RT_ELEMENTS(aPollFds), msTimeoutLeft); 1034 if (rcPsx != -1 || errno != EINTR) 1035 break; 1036 /* Restart when getting interrupted. */ 1037 if (msTimeoutLeft > -1) 948 1038 { 949 switch (bWakeupReason) 1039 uint64_t tsPollEnd = RTTimeMilliTS(); 1040 uint64_t tsPollSpan = tsPollEnd - tsPollStart; 1041 msTimeoutLeft -= RT_MIN(tsPollSpan, (uint32_t)msTimeoutLeft); 1042 } 1043 } 1044 1045 uint32_t fEvtsPending = 0; 1046 if (rcPsx < 0 && errno != EINTR) 1047 rc = RTErrConvertFromErrno(errno); 1048 else if (rcPsx > 0) 1049 { 1050 if (aPollFds[0].revents != 0) 1051 { 1052 fEvtsPending |= (aPollFds[0].revents & POLLIN) ? RTSERIALPORT_EVT_F_DATA_RX : 0; 1053 fEvtsPending |= (aPollFds[0].revents & POLLOUT) ? RTSERIALPORT_EVT_F_DATA_TX : 0; 1054 /** @todo BREAK condition detection. */ 1055 } 1056 1057 if (aPollFds[1].revents != 0) 1058 { 1059 AssertReturn(!(aPollFds[1].revents & (POLLHUP | POLLERR | POLLNVAL)), VERR_INTERNAL_ERROR); 1060 Assert(aPollFds[1].revents & POLLIN); 1061 1062 uint8_t bWakeupReason = 0; 1063 ssize_t cbRead = read(pThis->iFdPipeR, &bWakeupReason, 1); 1064 if (cbRead == 1) 950 1065 { 951 case RTSERIALPORT_WAKEUP_PIPE_REASON_INTERRUPT: 952 rc = VERR_INTERRUPTED; 953 break; 954 case RTSERIALPORT_WAKEUP_PIPE_REASON_STS_LINE_CHANGED: 955 fEvtsPending |= RTSERIALPORT_EVT_F_STATUS_LINE_CHANGED; 956 break; 957 case RTSERIALPORT_WAKEUP_PIPE_REASON_STS_LINE_MONITOR_FAILED: 958 fEvtsPending |= RTSERIALPORT_EVT_F_STATUS_LINE_MONITOR_FAILED; 959 break; 960 default: 961 AssertFailed(); 962 rc = VERR_INTERNAL_ERROR; 1066 switch (bWakeupReason) 1067 { 1068 case RTSERIALPORT_WAKEUP_PIPE_REASON_INTERRUPT: 1069 rc = VERR_INTERRUPTED; 1070 break; 1071 case RTSERIALPORT_WAKEUP_PIPE_REASON_STS_LINE_CHANGED: 1072 fEvtsPending |= RTSERIALPORT_EVT_F_STATUS_LINE_CHANGED; 1073 break; 1074 case RTSERIALPORT_WAKEUP_PIPE_REASON_STS_LINE_MONITOR_FAILED: 1075 fEvtsPending |= RTSERIALPORT_EVT_F_STATUS_LINE_MONITOR_FAILED; 1076 break; 1077 default: 1078 AssertFailed(); 1079 rc = VERR_INTERNAL_ERROR; 1080 } 963 1081 } 1082 else 1083 rc = VERR_INTERNAL_ERROR; 964 1084 } 965 else 966 rc = VERR_INTERNAL_ERROR; 967 } 968 } 969 else 970 rc = VERR_TIMEOUT; 971 972 *pfEvtsRecv = fEvtsPending & fEvtMask; 973 fEvtsPending &= ~fEvtMask; 974 ASMAtomicOrU32(&pThis->fEvtsPending, fEvtsPending); 1085 } 1086 else 1087 rc = VERR_TIMEOUT; 1088 1089 *pfEvtsRecv = fEvtsPending & fEvtMask; 1090 fEvtsPending &= ~fEvtMask; 1091 ASMAtomicOrU32(&pThis->fEvtsPending, fEvtsPending); 1092 } 975 1093 976 1094 return rc; -
trunk/src/VBox/Runtime/r3/win/serialport-win.cpp
r69986 r71028 335 335 AssertReturn(cbToRead > 0, VERR_INVALID_PARAMETER); 336 336 337 RT_NOREF(pcbRead); 338 int rc = VERR_NOT_IMPLEMENTED; 337 /* 338 * Kick of an overlapped read. 339 */ 340 int rc = VINF_SUCCESS; 341 uint8_t *pbBuf = (uint8_t *)pvBuf; 342 343 while ( cbToRead > 0 344 && RT_SUCCESS(rc)) 345 { 346 BOOL fSucc = ResetEvent(pThis->Overlapped.hEvent); Assert(fSucc == TRUE); RT_NOREF(fSucc); 347 DWORD cbRead = 0; 348 if (ReadFile(pThis->hDev, pbBuf, 349 cbToRead <= ~(DWORD)0 ? (DWORD)cbToRead : ~(DWORD)0, 350 &cbRead, &pThis->Overlapped)) 351 { 352 if (pcbRead) 353 { 354 *pcbRead = cbRead; 355 break; 356 } 357 rc = VINF_SUCCESS; 358 } 359 else if (GetLastError() == ERROR_IO_PENDING) 360 { 361 DWORD dwWait = WaitForSingleObject(pThis->Overlapped.hEvent, INFINITE); 362 if (dwWait == WAIT_OBJECT_0) 363 { 364 if (GetOverlappedResult(pThis->hDev, &pThis->Overlapped, &cbRead, TRUE /*fWait*/)) 365 { 366 if (pcbRead) 367 { 368 *pcbRead = cbRead; 369 break; 370 } 371 rc = VINF_SUCCESS; 372 } 373 else 374 rc = RTErrConvertFromWin32(GetLastError()); 375 } 376 else 377 { 378 Assert(dwWait == WAIT_FAILED); 379 rc = RTErrConvertFromWin32(GetLastError()); 380 } 381 } 382 else 383 rc = RTErrConvertFromWin32(GetLastError()); 384 385 if (RT_SUCCESS(rc)) 386 { 387 cbToRead -= cbRead; 388 pbBuf += cbRead; 389 } 390 } 391 339 392 return rc; 340 393 } … … 394 447 RTDECL(int) RTSerialPortWrite(RTSERIALPORT hSerialPort, const void *pvBuf, size_t cbToWrite, size_t *pcbWritten) 395 448 { 396 RT_NOREF(hSerialPort, pvBuf, cbToWrite, pcbWritten); 397 return VERR_NOT_IMPLEMENTED; 449 PRTSERIALPORTINTERNAL pThis = hSerialPort; 450 AssertPtrReturn(pThis, VERR_INVALID_PARAMETER); 451 AssertReturn(pThis->u32Magic == RTSERIALPORT_MAGIC, VERR_INVALID_HANDLE); 452 AssertPtrReturn(pvBuf, VERR_INVALID_POINTER); 453 AssertReturn(cbToWrite > 0, VERR_INVALID_PARAMETER); 454 455 /* If I/O is pending, check if it has completed. */ 456 int rc = VINF_SUCCESS; 457 if (pThis->fWritePending) 458 rc = rtSerialPortWriteCheckCompletion(pThis); 459 if (rc == VINF_SUCCESS) 460 { 461 const uint8_t *pbBuf = (const uint8_t *)pvBuf; 462 463 while ( cbToWrite > 0 464 && RT_SUCCESS(rc)) 465 { 466 BOOL fSucc = ResetEvent(pThis->Overlapped.hEvent); Assert(fSucc == TRUE); RT_NOREF(fSucc); 467 DWORD cbWritten = 0; 468 if (WriteFile(pThis->hDev, pbBuf, 469 cbToWrite <= ~(DWORD)0 ? (DWORD)cbToWrite : ~(DWORD)0, 470 &cbWritten, &pThis->Overlapped)) 471 { 472 if (pcbWritten) 473 { 474 *pcbWritten = cbWritten; 475 break; 476 } 477 rc = VINF_SUCCESS; 478 } 479 else if (GetLastError() == ERROR_IO_PENDING) 480 { 481 DWORD dwWait = WaitForSingleObject(pThis->Overlapped.hEvent, INFINITE); 482 if (dwWait == WAIT_OBJECT_0) 483 { 484 if (GetOverlappedResult(pThis->hDev, &pThis->Overlapped, &cbWritten, TRUE /*fWait*/)) 485 { 486 if (pcbWritten) 487 { 488 *pcbWritten = cbWritten; 489 break; 490 } 491 rc = VINF_SUCCESS; 492 } 493 else 494 rc = RTErrConvertFromWin32(GetLastError()); 495 } 496 else 497 { 498 Assert(dwWait == WAIT_FAILED); 499 rc = RTErrConvertFromWin32(GetLastError()); 500 } 501 } 502 else 503 rc = RTErrConvertFromWin32(GetLastError()); 504 505 if (RT_SUCCESS(rc)) 506 { 507 cbToWrite -= cbWritten; 508 pbBuf += cbWritten; 509 } 510 } 511 } 512 513 return rc; 398 514 } 399 515
Note:
See TracChangeset
for help on using the changeset viewer.