VirtualBox

Ticket #812: serhsk.diff

File serhsk.diff, 4.5 KB (added by Lawrence Rust, 14 years ago)

Fix serial handshake

  • src/VBox/Devices/Serial/DrvHostSerial.cpp

     
    365365
    366366    tcsetattr(pThis->DeviceFile, TCSANOW, termiosSetup);
    367367    RTMemTmpFree(termiosSetup);
     368
     369#ifdef RT_OS_LINUX
     370    /* BUGBUG: In Linux 2.6.24 and earlier, if a thread calls tcsetattr while the monitor
     371     * thread is waiting in ioctl for a modem status change then 8250.c wrongly disables
     372     * modem irqs and so the monitor thread never gets released.  The workaround is to send
     373     * a signal after each tcsetattr
     374     */
     375    RTThreadPoke(pThis->pMonitorThread->Thread);
     376#endif
     377
    368378#elif defined(RT_OS_WINDOWS)
    369379    comSetup = (LPDCB)RTMemTmpAllocZ(sizeof(DCB));
    370380
     
    961971{
    962972    PDRVHOSTSERIAL pThis = PDMINS_2_DATA(pDrvIns, PDRVHOSTSERIAL);
    963973    int rc = VINF_SUCCESS;
    964     unsigned uStatusLinesToCheck = 0;
     974    unsigned long const uStatusLinesToCheck = TIOCM_CAR | TIOCM_RNG | TIOCM_DSR | TIOCM_CTS;
    965975
    966     uStatusLinesToCheck = TIOCM_CAR | TIOCM_RNG | TIOCM_LE | TIOCM_CTS;
    967 
    968976    if (pThread->enmState == PDMTHREADSTATE_INITIALIZING)
    969977        return VINF_SUCCESS;
    970978
    971     while (pThread->enmState == PDMTHREADSTATE_RUNNING)
     979    do
    972980    {
    973         uint32_t newStatusLine = 0;
    974981        unsigned int statusLines;
    975982
    976 # ifdef RT_OS_LINUX
    977         /*
    978          * Wait for status line change.
    979          */
    980         rc = ioctl(pThis->DeviceFile, TIOCMIWAIT, uStatusLinesToCheck);
    981         if (pThread->enmState != PDMTHREADSTATE_RUNNING)
    982             break;
    983         if (rc < 0)
     983        if ( 0 > (rc = ioctl( pThis->DeviceFile, TIOCMGET, &statusLines)))
    984984        {
    985 ioctl_error:
    986985            PDMDrvHlpVMSetRuntimeError(pDrvIns, 0 /*fFlags*/, "DrvHostSerialFail",
    987986                                       N_("Ioctl failed for serial host device '%s' (%Rrc). The device will not work properly"),
    988987                                       pThis->pszDevicePath, RTErrConvertFromErrno(errno));
    989988            break;
    990989        }
    991990
    992         rc = ioctl(pThis->DeviceFile, TIOCMGET, &statusLines);
    993         if (rc < 0)
    994             goto ioctl_error;
    995 # else  /* !RT_OS_LINUX */
    996         /*
    997          * Poll for the status line change.
    998          */
    999         rc = ioctl(pThis->DeviceFile, TIOCMGET, &statusLines);
    1000         if (rc < 0)
    1001         {
    1002             PDMDrvHlpVMSetRuntimeError(pDrvIns, 0 /*fFlags*/, "DrvHostSerialFail",
    1003                                        N_("Ioctl failed for serial host device '%s' (%Rrc). The device will not work properly"),
    1004                                        pThis->pszDevicePath, RTErrConvertFromErrno(errno));
    1005             break;
    1006         }
    1007         if (!((statusLines ^ pThis->fStatusLines) & uStatusLinesToCheck))
    1008         {
    1009             PDMR3ThreadSleep(pThread, 500); /* 0.5 sec */
    1010             continue;
    1011         }
    1012         pThis->fStatusLines = statusLines;
    1013 # endif /* !RT_OS_LINUX */
    1014 
     991        uint32_t newStatusLine = 0;
    1015992        if (statusLines & TIOCM_CAR)
    1016993            newStatusLine |= PDMICHARPORT_STATUS_LINES_DCD;
    1017994        if (statusLines & TIOCM_RNG)
    1018995            newStatusLine |= PDMICHARPORT_STATUS_LINES_RI;
    1019         if (statusLines & TIOCM_LE)
     996        if (statusLines & TIOCM_DSR)
    1020997            newStatusLine |= PDMICHARPORT_STATUS_LINES_DSR;
    1021998        if (statusLines & TIOCM_CTS)
    1022999            newStatusLine |= PDMICHARPORT_STATUS_LINES_CTS;
    1023         rc = pThis->pDrvCharPort->pfnNotifyStatusLinesChanged(pThis->pDrvCharPort, newStatusLine);
     1000        pThis->pDrvCharPort->pfnNotifyStatusLinesChanged(pThis->pDrvCharPort, newStatusLine);
     1001
     1002        if ( PDMTHREADSTATE_RUNNING != pThread->enmState)
     1003            break;
     1004# ifdef RT_OS_LINUX
     1005        /* Wait for status line change. */
     1006        /* BUGBUG: In Linux 2.6.24 and earlier, if a thread calls tcsetattr while the monitor
     1007         * thread is waiting in ioctl for a modem status change then 8250.c wrongly disables
     1008         * modem irqs and so the monitor thread never gets released.  The workaround is to send
     1009         * a signal after each tcsetattr
     1010         */
     1011        ioctl( pThis->DeviceFile, TIOCMIWAIT, uStatusLinesToCheck);
     1012# else
     1013        /* Poll for status line change. */
     1014        if (!((statusLines ^ pThis->fStatusLines) & uStatusLinesToCheck))
     1015            PDMR3ThreadSleep( pThread, 500); /* 0.5 sec */
     1016        pThis->fStatusLines = statusLines;
     1017# endif
    10241018    }
     1019    while (PDMTHREADSTATE_RUNNING == pThread->enmState);
    10251020
    1026     return VINF_SUCCESS;
     1021    return rc;
    10271022}
    10281023
    10291024/**

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