Merge pull request #6106 from Cacodemon345/linux-port-fixes

Pass through serial lines between serial port and emulator
This commit is contained in:
Miran Grča
2025-08-29 21:26:36 +02:00
committed by GitHub
4 changed files with 77 additions and 1 deletions

View File

@@ -75,6 +75,8 @@ host_to_serial_cb(void *priv)
uint8_t byte; uint8_t byte;
plat_serpt_set_line_state(priv);
/* write_fifo has no failure indication, but if we write to fast, the host /* write_fifo has no failure indication, but if we write to fast, the host
* can never fetch the bytes in time, so check if the fifo is full if in * can never fetch the bytes in time, so check if the fifo is full if in
* fifo mode or if lsr has bit 0 set if not in fifo mode */ * fifo mode or if lsr has bit 0 set if not in fifo mode */

View File

@@ -30,6 +30,7 @@ extern int plat_serpt_read(void *priv, uint8_t *data);
extern int plat_serpt_open_device(void *priv); extern int plat_serpt_open_device(void *priv);
extern void plat_serpt_close(void *priv); extern void plat_serpt_close(void *priv);
extern void plat_serpt_set_params(void *priv); extern void plat_serpt_set_params(void *priv);
extern void plat_serpt_set_line_state(void *priv);
#ifdef __cplusplus #ifdef __cplusplus
} }

View File

@@ -82,10 +82,31 @@ plat_serpt_write_vcon(serial_passthrough_t *dev, uint8_t data)
WriteFile((HANDLE) dev->master_fd, &data, 1, &bytesWritten, NULL); WriteFile((HANDLE) dev->master_fd, &data, 1, &bytesWritten, NULL);
} }
void
plat_serpt_set_line_state(void *priv)
{
const serial_passthrough_t *dev = (serial_passthrough_t *) priv;
if (dev->mode == SERPT_MODE_HOSTSER) {
DWORD msrstate;
EscapeCommFunction((HANDLE) dev->master_fd, (dev->serial->mctrl & 1) ? SETDTR : CLRDTR);
EscapeCommFunction((HANDLE) dev->master_fd, (dev->serial->mctrl & 2) ? SETRTS : CLRRTS);
EscapeCommFunction((HANDLE) dev->master_fd, (dev->serial->lcr & (1 << 6) ? SETBREAK : CLRBREAK));
if (GetCommModemStatus((HANDLE) dev->master_fd, &msrstate)) {
serial_set_dcd(dev->serial, !!(msrstate & MS_RLSD_ON));
serial_set_dsr(dev->serial, !!(msrstate & MS_DSR_ON));
serial_set_cts(dev->serial, !!(msrstate & MS_CTS_ON));
serial_set_ri(dev->serial, !!(msrstate & MS_RING_ON));
}
}
}
void void
plat_serpt_set_params(void *priv) plat_serpt_set_params(void *priv)
{ {
const serial_passthrough_t *dev = (serial_passthrough_t *) priv; const serial_passthrough_t *dev = (serial_passthrough_t *) priv;
WINBOOL result;
if (dev->mode == SERPT_MODE_HOSTSER) { if (dev->mode == SERPT_MODE_HOSTSER) {
DCB serialattr = { 0 }; DCB serialattr = { 0 };
@@ -108,6 +129,13 @@ plat_serpt_set_params(void *priv)
BAUDRATE_RANGE(dev->baudrate, 57600, 115200); BAUDRATE_RANGE(dev->baudrate, 57600, 115200);
BAUDRATE_RANGE(dev->baudrate, 115200, 0xFFFFFFFF); BAUDRATE_RANGE(dev->baudrate, 115200, 0xFFFFFFFF);
serialattr.fRtsControl = RTS_CONTROL_ENABLE;
serialattr.fDtrControl = DTR_CONTROL_ENABLE;
serialattr.fDsrSensitivity = FALSE;
serialattr.fAbortOnError = FALSE;
serialattr.fInX = FALSE;
serialattr.fOutX = FALSE;
serialattr.ByteSize = dev->data_bits; serialattr.ByteSize = dev->data_bits;
serialattr.StopBits = (dev->serial->lcr & 0x04) ? TWOSTOPBITS : ONESTOPBIT; serialattr.StopBits = (dev->serial->lcr & 0x04) ? TWOSTOPBITS : ONESTOPBIT;
if (!(dev->serial->lcr & 0x08)) { if (!(dev->serial->lcr & 0x08)) {
@@ -122,7 +150,21 @@ plat_serpt_set_params(void *priv)
} }
} }
SetCommState((HANDLE) dev->master_fd, &serialattr); result = SetCommState((HANDLE) dev->master_fd, &serialattr);
{
DWORD msrstate;
EscapeCommFunction((HANDLE) dev->master_fd, (dev->serial->mctrl & 1) ? SETDTR : CLRDTR);
EscapeCommFunction((HANDLE) dev->master_fd, (dev->serial->mctrl & 2) ? SETRTS : CLRRTS);
EscapeCommFunction((HANDLE) dev->master_fd, (dev->serial->lcr & (1 << 6) ? SETBREAK : CLRBREAK));
if (GetCommModemStatus((HANDLE) dev->master_fd, &msrstate)) {
serial_set_dcd(dev->serial, !!(msrstate & MS_RLSD_ON));
serial_set_dsr(dev->serial, !!(msrstate & MS_DSR_ON));
serial_set_cts(dev->serial, !!(msrstate & MS_CTS_ON));
serial_set_ri(dev->serial, !!(msrstate & MS_RING_ON));
}
}
#undef BAUDRATE_RANGE #undef BAUDRATE_RANGE
} }
} }

View File

@@ -36,6 +36,7 @@
#include <sys/select.h> #include <sys/select.h>
#include <stdint.h> #include <stdint.h>
#include <sys/select.h> #include <sys/select.h>
#include <sys/ioctl.h>
#include <86box/86box.h> #include <86box/86box.h>
#include <86box/log.h> #include <86box/log.h>
@@ -48,6 +49,35 @@
#define LOG_PREFIX "serial_passthrough: " #define LOG_PREFIX "serial_passthrough: "
void
plat_serpt_set_line_state(void *priv)
{
serial_passthrough_t *dev = (serial_passthrough_t *) priv;
int setstate = 0, clrstate = 0, curstate = 0;
if (dev->mode != SERPT_MODE_HOSTSER)
return;
if (dev->serial->lcr & (1 << 6)) {
tcsendbreak(dev->master_fd, 0);
}
ioctl(dev->master_fd, TIOCMGET, &curstate);
clrstate |= !(dev->serial->mctrl & 1) ? TIOCM_DTR : 0;
clrstate |= !(dev->serial->mctrl & 2) ? TIOCM_RTS : 0;
setstate |= (dev->serial->mctrl & 1) ? TIOCM_DTR : 0;
setstate |= (dev->serial->mctrl & 2) ? TIOCM_RTS : 0;
ioctl(dev->master_fd, TIOCMBIS, &setstate);
ioctl(dev->master_fd, TIOCMBIC, &clrstate);
serial_set_cts(dev->serial, !!(curstate & TIOCM_CTS));
serial_set_dcd(dev->serial, !!(curstate & TIOCM_CAR));
serial_set_dsr(dev->serial, !!(curstate & TIOCM_DSR));
serial_set_ri(dev->serial, !!(curstate & TIOCM_RI));
}
int int
plat_serpt_read(void *priv, uint8_t *data) plat_serpt_read(void *priv, uint8_t *data)
{ {
@@ -194,6 +224,7 @@ plat_serpt_set_params(void *priv)
term_attr.c_cflag |= CMSPAR; term_attr.c_cflag |= CMSPAR;
#endif #endif
} }
term_attr.c_iflag &= ~(IXON | IXOFF);
tcsetattr(dev->master_fd, TCSANOW, &term_attr); tcsetattr(dev->master_fd, TCSANOW, &term_attr);
#undef BAUDRATE_RANGE #undef BAUDRATE_RANGE
} }