VirtualBox

Changeset 73635 in vbox for trunk/src/VBox


Ignore:
Timestamp:
Aug 13, 2018 1:01:07 PM (6 years ago)
Author:
vboxsync
Message:

Runtime/serialport-win.cpp: Fixes for I/O

File:
1 edited

Legend:

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

    r73630 r73635  
    6060    /** The device handle. */
    6161    HANDLE              hDev;
    62     /** The overlapped I/O structure. */
    63     OVERLAPPED          Overlapped;
    64     /** The event handle to wait on for the overlapped I/O operations of the device. */
     62    /** The overlapped write structure. */
     63    OVERLAPPED          OverlappedWrite;
     64    /** The overlapped read structure. */
     65    OVERLAPPED          OverlappedRead;
     66    /** The overlapped I/O structure when waiting on events. */
     67    OVERLAPPED          OverlappedEvt;
     68    /** The event handle to wait on for the overlapped event operations of the device. */
    6569    HANDLE              hEvtDev;
     70    /** The event handle to wait on for the overlapped write operations of the device. */
     71    HANDLE              hEvtWrite;
     72    /** The event handle to wait on for the overlapped read operations of the device. */
     73    HANDLE              hEvtRead;
    6674    /** The event handle to wait on for waking up waiting threads externally. */
    6775    HANDLE              hEvtIntr;
     
    111119static int rtSerialPortWinUpdateEvtMask(PRTSERIALPORTINTERNAL pThis, uint32_t fEvtMask)
    112120{
    113     DWORD dwEvtMask = 0;
     121    DWORD dwEvtMask = EV_ERR;
    114122
    115123    if (fEvtMask & RTSERIALPORT_EVT_F_DATA_RX)
     
    173181{
    174182    int rc = VINF_SUCCESS;
    175     DWORD dwRc = WaitForSingleObject(pThis->Overlapped.hEvent, 0);
     183    DWORD dwRc = WaitForSingleObject(pThis->OverlappedWrite.hEvent, 0);
    176184    if (dwRc == WAIT_OBJECT_0)
    177185    {
    178186        DWORD cbWritten = 0;
    179         if (GetOverlappedResult(pThis->hDev, &pThis->Overlapped, &cbWritten, TRUE))
     187        if (GetOverlappedResult(pThis->hDev, &pThis->OverlappedWrite, &cbWritten, TRUE))
    180188        {
    181189            for (;;)
     
    190198                /* resubmit the remainder of the buffer - can this actually happen? */
    191199                memmove(&pThis->pbBounceBuf[0], &pThis->pbBounceBuf[cbWritten], pThis->cbBounceBufUsed - cbWritten);
    192                 rc = ResetEvent(pThis->Overlapped.hEvent); Assert(rc == TRUE);
     200                rc = ResetEvent(pThis->OverlappedWrite.hEvent); Assert(rc == TRUE);
    193201                if (!WriteFile(pThis->hDev, pThis->pbBounceBuf, (DWORD)pThis->cbBounceBufUsed,
    194                                &cbWritten, &pThis->Overlapped))
     202                               &cbWritten, &pThis->OverlappedWrite))
    195203                {
    196204                    if (GetLastError() == ERROR_IO_PENDING)
     
    245253        pThis->cbBounceBufUsed  = 0;
    246254        pThis->cbBounceBufAlloc = 0;
    247         pThis->hEvtDev          = CreateEvent(NULL, FALSE, FALSE, NULL);
     255        RT_ZERO(pThis->OverlappedEvt);
     256        RT_ZERO(pThis->OverlappedWrite);
     257        RT_ZERO(pThis->OverlappedRead);
     258        pThis->hEvtDev          = CreateEvent(NULL, TRUE, FALSE, NULL);
    248259        if (pThis->hEvtDev)
    249260        {
    250             pThis->Overlapped.hEvent = pThis->hEvtDev,
     261            pThis->OverlappedEvt.hEvent = pThis->hEvtDev,
    251262            pThis->hEvtIntr = CreateEvent(NULL, FALSE, FALSE, NULL);
    252263            if (pThis->hEvtIntr)
    253264            {
    254                 DWORD fWinFlags = 0;
    255 
    256                 if (fFlags & RTSERIALPORT_OPEN_F_WRITE)
    257                     fWinFlags |= GENERIC_WRITE;
    258                 if (fFlags & RTSERIALPORT_OPEN_F_READ)
    259                     fWinFlags |= GENERIC_READ;
    260 
    261                 pThis->hDev = CreateFile(pszPortAddress,
    262                                          fWinFlags,
    263                                          0, /* Must be opened with exclusive access. */
    264                                          NULL, /* No SECURITY_ATTRIBUTES structure. */
    265                                          OPEN_EXISTING, /* Must use OPEN_EXISTING. */
    266                                          FILE_FLAG_OVERLAPPED, /* Overlapped I/O. */
    267                                          NULL);
    268                 if (pThis->hDev)
     265                pThis->hEvtWrite = CreateEvent(NULL, TRUE, TRUE, NULL);
     266                if (pThis->hEvtWrite)
    269267                {
    270                     rc = rtSerialPortSetDefaultCfg(pThis);
    271                     if (RT_SUCCESS(rc))
     268                    pThis->OverlappedWrite.hEvent = pThis->hEvtWrite;
     269                    pThis->hEvtRead = CreateEvent(NULL, TRUE, TRUE, NULL);
     270                    if (pThis->hEvtRead)
    272271                    {
    273                         *phSerialPort = pThis;
    274                         return rc;
     272                        pThis->OverlappedRead.hEvent = pThis->hEvtRead;
     273                        DWORD fWinFlags = 0;
     274
     275                        if (fFlags & RTSERIALPORT_OPEN_F_WRITE)
     276                            fWinFlags |= GENERIC_WRITE;
     277                        if (fFlags & RTSERIALPORT_OPEN_F_READ)
     278                            fWinFlags |= GENERIC_READ;
     279
     280                        pThis->hDev = CreateFile(pszPortAddress,
     281                                                 fWinFlags,
     282                                                 0, /* Must be opened with exclusive access. */
     283                                                 NULL, /* No SECURITY_ATTRIBUTES structure. */
     284                                                 OPEN_EXISTING, /* Must use OPEN_EXISTING. */
     285                                                 FILE_FLAG_OVERLAPPED, /* Overlapped I/O. */
     286                                                 NULL);
     287                        if (pThis->hDev)
     288                        {
     289                            rc = rtSerialPortSetDefaultCfg(pThis);
     290                            if (RT_SUCCESS(rc))
     291                            {
     292                                *phSerialPort = pThis;
     293                                return rc;
     294                            }
     295                        }
     296                        else
     297                            rc = RTErrConvertFromWin32(GetLastError());
     298
     299                        CloseHandle(pThis->hEvtRead);
    275300                    }
     301
     302                    CloseHandle(pThis->hEvtWrite);
    276303                }
    277                 else
    278                     rc = RTErrConvertFromWin32(GetLastError());
    279304
    280305                CloseHandle(pThis->hEvtIntr);
     
    315340    CloseHandle(pThis->hDev);
    316341    CloseHandle(pThis->hEvtDev);
     342    CloseHandle(pThis->hEvtWrite);
     343    CloseHandle(pThis->hEvtRead);
    317344    CloseHandle(pThis->hEvtIntr);
    318     pThis->hDev     = NULL;
    319     pThis->hEvtDev  = NULL;
    320     pThis->hEvtIntr = NULL;
     345    pThis->hDev      = NULL;
     346    pThis->hEvtDev   = NULL;
     347    pThis->hEvtWrite = NULL;
     348    pThis->hEvtRead  = NULL;
     349    pThis->hEvtIntr  = NULL;
    321350    RTMemFree(pThis);
    322351    return VINF_SUCCESS;
     
    351380           && RT_SUCCESS(rc))
    352381    {
    353         BOOL fSucc = ResetEvent(pThis->Overlapped.hEvent); Assert(fSucc == TRUE); RT_NOREF(fSucc);
     382        BOOL fSucc = ResetEvent(pThis->OverlappedRead.hEvent); Assert(fSucc == TRUE); RT_NOREF(fSucc);
    354383        DWORD cbRead = 0;
    355384        if (ReadFile(pThis->hDev, pbBuf,
    356385                     cbToRead <= ~(DWORD)0 ? (DWORD)cbToRead : ~(DWORD)0,
    357                      &cbRead, &pThis->Overlapped))
     386                     &cbRead, &pThis->OverlappedRead))
    358387        {
    359388            if (pcbRead)
     
    366395        else if (GetLastError() == ERROR_IO_PENDING)
    367396        {
    368             DWORD dwWait = WaitForSingleObject(pThis->Overlapped.hEvent, INFINITE);
     397            DWORD dwWait = WaitForSingleObject(pThis->OverlappedRead.hEvent, INFINITE);
    369398            if (dwWait == WAIT_OBJECT_0)
    370399            {
    371                 if (GetOverlappedResult(pThis->hDev, &pThis->Overlapped, &cbRead, TRUE /*fWait*/))
     400                if (GetOverlappedResult(pThis->hDev, &pThis->OverlappedRead, &cbRead, TRUE /*fWait*/))
    372401                {
    373402                    if (pcbRead)
     
    418447     */
    419448    int rc = VINF_SUCCESS;
    420     BOOL fSucc = ResetEvent(pThis->Overlapped.hEvent); Assert(fSucc == TRUE); RT_NOREF(fSucc);
     449    BOOL fSucc = ResetEvent(pThis->OverlappedRead.hEvent); Assert(fSucc == TRUE); RT_NOREF(fSucc);
    421450    DWORD cbRead = 0;
    422451    if (   cbToRead == 0
    423452        || ReadFile(pThis->hDev, pvBuf,
    424453                    cbToRead <= ~(DWORD)0 ? (DWORD)cbToRead : ~(DWORD)0,
    425                     &cbRead, &pThis->Overlapped))
     454                    &cbRead, &pThis->OverlappedRead))
    426455    {
    427456        *pcbRead = cbRead;
     
    431460    {
    432461        if (!CancelIo(pThis->hDev))
    433             WaitForSingleObject(pThis->Overlapped.hEvent, INFINITE);
    434         if (GetOverlappedResult(pThis->hDev, &pThis->Overlapped, &cbRead, TRUE /*fWait*/))
     462            WaitForSingleObject(pThis->OverlappedRead.hEvent, INFINITE);
     463        if (GetOverlappedResult(pThis->hDev, &pThis->OverlappedRead, &cbRead, TRUE /*fWait*/))
    435464        {
    436465            *pcbRead = cbRead;
     
    471500               && RT_SUCCESS(rc))
    472501        {
    473             BOOL fSucc = ResetEvent(pThis->Overlapped.hEvent); Assert(fSucc == TRUE); RT_NOREF(fSucc);
     502            BOOL fSucc = ResetEvent(pThis->OverlappedWrite.hEvent); Assert(fSucc == TRUE); RT_NOREF(fSucc);
    474503            DWORD cbWritten = 0;
    475504            if (WriteFile(pThis->hDev, pbBuf,
    476505                          cbToWrite <= ~(DWORD)0 ? (DWORD)cbToWrite : ~(DWORD)0,
    477                           &cbWritten, &pThis->Overlapped))
     506                          &cbWritten, &pThis->OverlappedWrite))
    478507            {
    479508                if (pcbWritten)
     
    486515            else if (GetLastError() == ERROR_IO_PENDING)
    487516            {
    488                 DWORD dwWait = WaitForSingleObject(pThis->Overlapped.hEvent, INFINITE);
     517                DWORD dwWait = WaitForSingleObject(pThis->OverlappedWrite.hEvent, INFINITE);
    489518                if (dwWait == WAIT_OBJECT_0)
    490519                {
    491                     if (GetOverlappedResult(pThis->hDev, &pThis->Overlapped, &cbWritten, TRUE /*fWait*/))
     520                    if (GetOverlappedResult(pThis->hDev, &pThis->OverlappedWrite, &cbWritten, TRUE /*fWait*/))
    492521                    {
    493522                        if (pcbWritten)
     
    562591
    563592            /* Submit the write. */
    564             rc = ResetEvent(pThis->Overlapped.hEvent); Assert(rc == TRUE);
     593            rc = ResetEvent(pThis->OverlappedWrite.hEvent); Assert(rc == TRUE);
    565594            DWORD cbWritten = 0;
    566595            if (WriteFile(pThis->hDev, pThis->pbBounceBuf, (DWORD)pThis->cbBounceBufUsed,
    567                           &cbWritten, &pThis->Overlapped))
     596                          &cbWritten, &pThis->OverlappedWrite))
    568597            {
    569598                *pcbWritten = RT_MIN(cbWritten, cbToWrite); /* paranoia^3 */
     
    750779        rc = rtSerialPortWinUpdateEvtMask(pThis, fEvtMask);
    751780
     781    /*
     782     * EV_RXCHAR is triggered only if a byte is received after the event mask is set,
     783     * not if there is already something in the input buffer. Thatswhy we check the input
     784     * buffer for any stored data and the output buffer whether it is empty and return
     785     * the appropriate flags.
     786     */
     787    if (RT_SUCCESS(rc))
     788    {
     789        COMSTAT ComStat; RT_ZERO(ComStat);
     790        if (!ClearCommError(pThis->hDev, NULL, &ComStat))
     791            return RTErrConvertFromWin32(GetLastError());
     792
     793        /* Check whether data is already waiting in the input buffer. */
     794        if (   (fEvtMask & RTSERIALPORT_EVT_F_DATA_RX)
     795            && ComStat.cbInQue > 0)
     796            *pfEvtsRecv |= RTSERIALPORT_EVT_F_DATA_RX;
     797
     798        /* Check whether the output buffer is empty. */
     799        if (   (fEvtMask & RTSERIALPORT_EVT_F_DATA_TX)
     800            && ComStat.cbOutQue == 0)
     801            *pfEvtsRecv |= RTSERIALPORT_EVT_F_DATA_TX;
     802
     803        /* Return if there is at least one event. */
     804        if (*pfEvtsRecv != 0)
     805            return VINF_SUCCESS;
     806    }
     807
    752808    if (RT_SUCCESS(rc))
    753809    {
     
    757813        ahWait[1] = pThis->hEvtIntr;
    758814
    759         RT_ZERO(pThis->Overlapped);
    760         pThis->Overlapped.hEvent = pThis->hEvtDev;
    761 
    762         if (!WaitCommEvent(pThis->hDev, &dwEventMask, &pThis->Overlapped))
     815        RT_ZERO(pThis->OverlappedEvt);
     816        pThis->OverlappedEvt.hEvent = pThis->hEvtDev;
     817
     818        if (!WaitCommEvent(pThis->hDev, &dwEventMask, &pThis->OverlappedEvt))
    763819        {
    764820            DWORD dwRet = GetLastError();
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