VirtualBox

Changeset 71956 in vbox for trunk/src/VBox


Ignore:
Timestamp:
Apr 22, 2018 11:50:09 AM (7 years ago)
Author:
vboxsync
Message:

Runtime/serialport-posix: Add custom baud rate support on Linux hosts

File:
1 edited

Legend:

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

    r71028 r71956  
    55
    66/*
    7  * Copyright (C) 2017 Oracle Corporation
     7 * Copyright (C) 2017-2018 Oracle Corporation
    88 *
    99 * This file is part of VirtualBox Open Source Edition (OSE), as
     
    108108    /** The current active config (we assume no one changes this behind our back). */
    109109    struct termios      PortCfg;
     110    /** Flag whether a custom baud rate was chosen (for hosts supporting this.). */
     111    bool                fBaudrateCust;
     112    /** The custom baud rate. */
     113    uint32_t            uBaudRateCust;
    110114} RTSERIALPORTINTERNAL;
    111115/** Pointer to the internal serial port state. */
     
    196200 *          could be found.
    197201 * @param   uBaudRate               The baud rate to convert.
    198  */
    199 DECLINLINE(speed_t) rtSerialPortGetTermiosSpeedFromBaudrate(uint32_t uBaudRate)
    200 {
     202 * @param   pfBaudrateCust          Where to store the flag whether a custom baudrate was selected.
     203 */
     204DECLINLINE(speed_t) rtSerialPortGetTermiosSpeedFromBaudrate(uint32_t uBaudRate, bool *pfBaudrateCust)
     205{
     206    *pfBaudrateCust = false;
     207
    201208    for (unsigned i = 0; i < RT_ELEMENTS(s_rtSerialPortBaudrateConv); i++)
    202209    {
     
    205212    }
    206213
     214#ifdef RT_OS_LINUX
     215    *pfBaudrateCust = true;
     216    return B38400;
     217#else
    207218    return B0;
     219#endif
    208220}
    209221
     
    217229static int rtSerialPortSetDefaultCfg(PRTSERIALPORTINTERNAL pThis)
    218230{
     231    pThis->fBaudrateCust = false;
     232    pThis->uBaudRateCust = 0;
    219233    pThis->PortCfg.c_iflag = INPCK; /* Input parity checking. */
    220234    cfsetispeed(&pThis->PortCfg, B9600);
     
    275289 * @param   pCfg                    Pointer to the serial port config descriptor.
    276290 * @param   pTermios                Pointer to the termios structure to fill.
     291 * @param   pfBaudrateCust          Where to store the flag whether a custom baudrate was selected.
    277292 * @param   pErrInfo                Additional error to be set when the conversion fails.
    278293 */
    279 static int rtSerialPortCfg2Termios(PRTSERIALPORTINTERNAL pThis, PCRTSERIALPORTCFG pCfg, struct termios *pTermios, PRTERRINFO pErrInfo)
     294static int rtSerialPortCfg2Termios(PRTSERIALPORTINTERNAL pThis, PCRTSERIALPORTCFG pCfg, struct termios *pTermios,
     295                                   bool *pfBaudrateCust, PRTERRINFO pErrInfo)
    280296{
    281297    RT_NOREF(pErrInfo); /** @todo Make use of the error info. */
    282     speed_t enmSpeed = rtSerialPortGetTermiosSpeedFromBaudrate(pCfg->uBaudRate);
     298    speed_t enmSpeed = rtSerialPortGetTermiosSpeedFromBaudrate(pCfg->uBaudRate, pfBaudrateCust);
    283299    if (enmSpeed != B0)
    284300    {
     
    367383        return VERR_SERIALPORT_INVALID_BAUDRATE;
    368384
    369 #ifdef RT_OS_LINUX
    370     /** @todo Handle custom baudrates supported by Linux. */
    371 #endif
    372 
    373385    return VINF_SUCCESS;
    374386}
     
    379391 *
    380392 * @returns IPRT status code.
     393 * @param   pThis                   The internal serial port instance data.
    381394 * @param   pTermios                The termios structure to convert.
    382395 * @param   pCfg                    The serial port config to fill in.
    383396 */
    384 static int rtSerialPortTermios2Cfg(struct termios *pTermios, PRTSERIALPORTCFG pCfg)
     397static int rtSerialPortTermios2Cfg(PRTSERIALPORTINTERNAL pThis, struct termios *pTermios, PRTSERIALPORTCFG pCfg)
    385398{
    386399    int rc = VINF_SUCCESS;
     
    389402    Assert(enmSpeedIn == cfgetospeed(pTermios)); /* Should always be the same. */
    390403
    391     pCfg->uBaudRate = rtSerialPortGetBaudrateFromTermiosSpeed(enmSpeedIn);
    392     if (!pCfg->uBaudRate)
    393         rc = VERR_SERIALPORT_INVALID_BAUDRATE;
     404    if (!pThis->fBaudrateCust)
     405    {
     406        pCfg->uBaudRate = rtSerialPortGetBaudrateFromTermiosSpeed(enmSpeedIn);
     407        if (!pCfg->uBaudRate)
     408            rc = VERR_SERIALPORT_INVALID_BAUDRATE;
     409    }
     410    else
     411        pCfg->uBaudRate = pThis->uBaudRateCust;
    394412
    395413    switch (pTermios->c_cflag & CSIZE)
     
    937955    AssertReturn(pThis->u32Magic == RTSERIALPORT_MAGIC, VERR_INVALID_HANDLE);
    938956
    939     return rtSerialPortTermios2Cfg(&pThis->PortCfg, pCfg);
     957    return rtSerialPortTermios2Cfg(pThis, &pThis->PortCfg, pCfg);
    940958}
    941959
     
    948966
    949967    struct termios PortCfgNew; RT_ZERO(PortCfgNew);
    950     int rc = rtSerialPortCfg2Termios(pThis, pCfg, &PortCfgNew, pErrInfo);
     968    bool fBaudrateCust = false;
     969    int rc = rtSerialPortCfg2Termios(pThis, pCfg, &PortCfgNew, &fBaudrateCust, pErrInfo);
    951970    if (RT_SUCCESS(rc))
    952971    {
     
    954973        if (!rcPsx)
    955974        {
    956             rcPsx = tcsetattr(pThis->iFd, TCSANOW, &PortCfgNew);
     975#ifdef RT_OS_LINUX
     976            if (fBaudrateCust)
     977            {
     978                struct serial_struct SerLnx;
     979                rcPsx = ioctl(pThis->iFd, TIOCGSERIAL, &SerLnx);
     980                if (!rcPsx)
     981                {
     982                    SerLnx.custom_divisor = SerLnx.baud_base / pCfg->uBaudRate;
     983                    if (!SerLnx.custom_divisor)
     984                        SerLnx.custom_divisor = 1;
     985                    SerLnx.flags &= ~ASYNC_SPD_MASK;
     986                    SerLnx.flags |= ASYNC_SPD_CUST;
     987                    rcPsx = ioctl(pThis->iFd, TIOCSSERIAL, &SerLnx);
     988                }
     989            }
     990#else /* !RT_OS_LINUX */
     991            /* Hosts not supporting custom baud rates should already fail in rtSerialPortCfg2Termios(). */
     992            AssertMsgFailed(("Should not get here!\n"));
     993#endif /* !RT_OS_LINUX */
     994            pThis->fBaudrateCust = fBaudrateCust;
     995            pThis->uBaudRateCust = pCfg->uBaudRate;
     996
     997            if (!rcPsx)
     998                rcPsx = tcsetattr(pThis->iFd, TCSANOW, &PortCfgNew);
    957999            if (rcPsx == -1)
    9581000                rc = RTErrConvertFromErrno(errno);
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