VirtualBox

Ignore:
Timestamp:
Feb 15, 2018 3:28:14 PM (7 years ago)
Author:
vboxsync
Message:

Runtime/RTSerialPort: Implement synchronous read/write methods for POSIX and Windows, allows the serial transport layer in TestExecService to work

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Runtime/r3/win/serialport-win.cpp

    r69986 r71028  
    335335    AssertReturn(cbToRead > 0, VERR_INVALID_PARAMETER);
    336336
    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
    339392    return rc;
    340393}
     
    394447RTDECL(int) RTSerialPortWrite(RTSERIALPORT hSerialPort, const void *pvBuf, size_t cbToWrite, size_t *pcbWritten)
    395448{
    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;
    398514}
    399515
Note: See TracChangeset for help on using the changeset viewer.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette