Serial Passthrough
This commit is contained in:
@@ -19,11 +19,14 @@
|
|||||||
* Copyright 2017-2020 Fred N. van Kempen.
|
* Copyright 2017-2020 Fred N. van Kempen.
|
||||||
* Copyright 2021 Laci bá'
|
* Copyright 2021 Laci bá'
|
||||||
* Copyright 2021 dob205
|
* Copyright 2021 dob205
|
||||||
|
* Copyright 2021 Andreas J. Reichel.
|
||||||
|
* Copyright 2021-2022 Jasmine Iwanek.
|
||||||
*/
|
*/
|
||||||
#include <inttypes.h>
|
#include <inttypes.h>
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
#include <stdbool.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
@@ -68,6 +71,7 @@
|
|||||||
#include <86box/isartc.h>
|
#include <86box/isartc.h>
|
||||||
#include <86box/lpt.h>
|
#include <86box/lpt.h>
|
||||||
#include <86box/serial.h>
|
#include <86box/serial.h>
|
||||||
|
#include <86box/serial_passthrough.h>
|
||||||
#include <86box/keyboard.h>
|
#include <86box/keyboard.h>
|
||||||
#include <86box/mouse.h>
|
#include <86box/mouse.h>
|
||||||
#include <86box/gameport.h>
|
#include <86box/gameport.h>
|
||||||
@@ -162,6 +166,7 @@ int video_filter_method = 1; /* (C) video */
|
|||||||
int video_vsync = 0; /* (C) video */
|
int video_vsync = 0; /* (C) video */
|
||||||
int video_framerate = -1; /* (C) video */
|
int video_framerate = -1; /* (C) video */
|
||||||
char video_shader[512] = { '\0' }; /* (C) video */
|
char video_shader[512] = { '\0' }; /* (C) video */
|
||||||
|
bool serial_passthrough_enabled[SERIAL_MAX] = { 0, 0, 0, 0 }; /* (C) activation and kind of pass-through for serial ports */
|
||||||
int bugger_enabled = 0; /* (C) enable ISAbugger */
|
int bugger_enabled = 0; /* (C) enable ISAbugger */
|
||||||
int postcard_enabled = 0; /* (C) enable POST card */
|
int postcard_enabled = 0; /* (C) enable POST card */
|
||||||
int isamem_type[ISAMEM_MAX] = { 0, 0, 0, 0 }; /* (C) enable ISA mem cards */
|
int isamem_type[ISAMEM_MAX] = { 0, 0, 0, 0 }; /* (C) enable ISA mem cards */
|
||||||
@@ -1038,6 +1043,7 @@ pc_reset_hard_init(void)
|
|||||||
|
|
||||||
/* Reset and reconfigure the serial ports. */
|
/* Reset and reconfigure the serial ports. */
|
||||||
serial_standalone_init();
|
serial_standalone_init();
|
||||||
|
serial_passthrough_init();
|
||||||
|
|
||||||
/* Reset and reconfigure the Sound Card layer. */
|
/* Reset and reconfigure the Sound Card layer. */
|
||||||
sound_card_reset();
|
sound_card_reset();
|
||||||
|
|||||||
19
src/config.c
19
src/config.c
@@ -20,6 +20,8 @@
|
|||||||
* Copyright 2016-2019 Miran Grca.
|
* Copyright 2016-2019 Miran Grca.
|
||||||
* Copyright 2017-2019 Fred N. van Kempen.
|
* Copyright 2017-2019 Fred N. van Kempen.
|
||||||
* Copyright 2018-2019 David Hrdlička.
|
* Copyright 2018-2019 David Hrdlička.
|
||||||
|
* Copyright 2021 Andreas J. Reichel.
|
||||||
|
* Copyright 2021-2022 Jasmine Iwanek.
|
||||||
*
|
*
|
||||||
* NOTE: Forcing config files to be in Unicode encoding breaks
|
* NOTE: Forcing config files to be in Unicode encoding breaks
|
||||||
* it on Windows XP, and possibly also Vista. Use the
|
* it on Windows XP, and possibly also Vista. Use the
|
||||||
@@ -54,6 +56,8 @@
|
|||||||
#include <86box/fdc.h>
|
#include <86box/fdc.h>
|
||||||
#include <86box/fdc_ext.h>
|
#include <86box/fdc_ext.h>
|
||||||
#include <86box/gameport.h>
|
#include <86box/gameport.h>
|
||||||
|
#include <86box/serial.h>
|
||||||
|
#include <86box/serial_passthrough.h>
|
||||||
#include <86box/machine.h>
|
#include <86box/machine.h>
|
||||||
#include <86box/mouse.h>
|
#include <86box/mouse.h>
|
||||||
#include <86box/thread.h>
|
#include <86box/thread.h>
|
||||||
@@ -81,6 +85,7 @@ static ini_t config;
|
|||||||
static int backwards_compat = 0;
|
static int backwards_compat = 0;
|
||||||
static int backwards_compat2 = 0;
|
static int backwards_compat2 = 0;
|
||||||
|
|
||||||
|
#define ENABLE_CONFIG_LOG 1
|
||||||
#ifdef ENABLE_CONFIG_LOG
|
#ifdef ENABLE_CONFIG_LOG
|
||||||
int config_do_log = ENABLE_CONFIG_LOG;
|
int config_do_log = ENABLE_CONFIG_LOG;
|
||||||
|
|
||||||
@@ -834,6 +839,8 @@ load_ports(void)
|
|||||||
char temp[512];
|
char temp[512];
|
||||||
int c, d;
|
int c, d;
|
||||||
|
|
||||||
|
memset(temp, 0, sizeof(temp));
|
||||||
|
|
||||||
for (c = 0; c < SERIAL_MAX; c++) {
|
for (c = 0; c < SERIAL_MAX; c++) {
|
||||||
sprintf(temp, "serial%d_enabled", c + 1);
|
sprintf(temp, "serial%d_enabled", c + 1);
|
||||||
com_ports[c].enabled = !!ini_section_get_int(cat, temp, (c >= 2) ? 0 : 1);
|
com_ports[c].enabled = !!ini_section_get_int(cat, temp, (c >= 2) ? 0 : 1);
|
||||||
@@ -843,6 +850,12 @@ load_ports(void)
|
|||||||
p = (char *) ini_section_get_string(cat, temp, "none");
|
p = (char *) ini_section_get_string(cat, temp, "none");
|
||||||
com_ports[c].device = com_device_get_from_internal_name(p);
|
com_ports[c].device = com_device_get_from_internal_name(p);
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
sprintf(temp, "serial%d_passthrough_enabled", c + 1);
|
||||||
|
serial_passthrough_enabled[c] = !!ini_section_get_int(cat, temp, 0);
|
||||||
|
|
||||||
|
if (serial_passthrough_enabled[c])
|
||||||
|
config_log("Serial Port %d: passthrough enabled.\n\n", c+1);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (c = 0; c < PARALLEL_MAX; c++) {
|
for (c = 0; c < PARALLEL_MAX; c++) {
|
||||||
@@ -2458,6 +2471,12 @@ save_ports(void)
|
|||||||
ini_section_set_string(cat, temp,
|
ini_section_set_string(cat, temp,
|
||||||
(char *) com_device_get_internal_name(com_ports[c].device));
|
(char *) com_device_get_internal_name(com_ports[c].device));
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
if (com_ports[c].enabled)
|
||||||
|
if (serial_passthrough_enabled[c]) {
|
||||||
|
sprintf(temp, "serial%d_passthrough_enabled", c + 1);
|
||||||
|
ini_section_set_int(cat, temp, 1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (c = 0; c < PARALLEL_MAX; c++) {
|
for (c = 0; c < PARALLEL_MAX; c++) {
|
||||||
|
|||||||
@@ -18,6 +18,8 @@
|
|||||||
* Copyright 2017-2019 Fred N. van Kempen.
|
* Copyright 2017-2019 Fred N. van Kempen.
|
||||||
* Copyright 2016-2019 Miran Grca.
|
* Copyright 2016-2019 Miran Grca.
|
||||||
* Copyright 2008-2019 Sarah Walker.
|
* Copyright 2008-2019 Sarah Walker.
|
||||||
|
* Copyright 2021 Andreas J. Reichel.
|
||||||
|
* Copyright 2021-2022 Jasmine Iwanek.
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* This program is free software; you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
@@ -91,6 +93,7 @@ device_set_context(device_context_t *c, const device_t *d, int inst)
|
|||||||
|
|
||||||
memset(c, 0, sizeof(device_context_t));
|
memset(c, 0, sizeof(device_context_t));
|
||||||
c->dev = d;
|
c->dev = d;
|
||||||
|
c->instance = inst;
|
||||||
if (inst) {
|
if (inst) {
|
||||||
sprintf(c->name, "%s #%i", d->name, inst);
|
sprintf(c->name, "%s #%i", d->name, inst);
|
||||||
|
|
||||||
@@ -556,6 +559,12 @@ device_force_redraw(void)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const int
|
||||||
|
device_get_instance(void)
|
||||||
|
{
|
||||||
|
return device_current.instance;
|
||||||
|
}
|
||||||
|
|
||||||
const char *
|
const char *
|
||||||
device_get_config_string(const char *s)
|
device_get_config_string(const char *s)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -11,13 +11,16 @@
|
|||||||
# Authors: David Hrdlička, <hrdlickadavid@outlook.com>
|
# Authors: David Hrdlička, <hrdlickadavid@outlook.com>
|
||||||
#
|
#
|
||||||
# Copyright 2020-2021 David Hrdlička.
|
# Copyright 2020-2021 David Hrdlička.
|
||||||
|
# Copyright 2021 Andreas J. Reichel.
|
||||||
|
# Copyright 2021-2022 Jasmine Iwanek.
|
||||||
#
|
#
|
||||||
|
|
||||||
add_library(dev OBJECT bugger.c cassette.c cartridge.c hasp.c hwm.c hwm_lm75.c hwm_lm78.c hwm_gl518sm.c
|
add_library(dev OBJECT bugger.c cassette.c cartridge.c hasp.c hwm.c hwm_lm75.c hwm_lm78.c hwm_gl518sm.c
|
||||||
hwm_vt82c686.c ibm_5161.c isamem.c isartc.c ../lpt.c pci_bridge.c
|
hwm_vt82c686.c ibm_5161.c isamem.c isartc.c ../lpt.c pci_bridge.c
|
||||||
postcard.c serial.c clock_ics9xxx.c isapnp.c i2c.c i2c_gpio.c
|
postcard.c serial.c clock_ics9xxx.c isapnp.c i2c.c i2c_gpio.c
|
||||||
smbus_piix4.c smbus_ali7101.c keyboard.c keyboard_xt.c keyboard_at.c
|
smbus_piix4.c smbus_ali7101.c keyboard.c keyboard_xt.c keyboard_at.c
|
||||||
mouse.c mouse_bus.c mouse_serial.c mouse_ps2.c phoenix_486_jumper.c)
|
mouse.c mouse_bus.c mouse_serial.c mouse_ps2.c phoenix_486_jumper.c
|
||||||
|
serial_passthrough.c)
|
||||||
|
|
||||||
if(ISAMEM_RAMPAGE)
|
if(ISAMEM_RAMPAGE)
|
||||||
target_compile_definitions(dev PRIVATE USE_ISAMEM_RAMPAGE)
|
target_compile_definitions(dev PRIVATE USE_ISAMEM_RAMPAGE)
|
||||||
|
|||||||
@@ -93,6 +93,8 @@ serial_transmit_period(serial_t *dev)
|
|||||||
|
|
||||||
/* Bit period based on DLAB. */
|
/* Bit period based on DLAB. */
|
||||||
dev->transmit_period = (16000000.0 * ddlab) / dev->clock_src;
|
dev->transmit_period = (16000000.0 * ddlab) / dev->clock_src;
|
||||||
|
if (dev->sd && dev->sd->transmit_period_callback)
|
||||||
|
dev->sd->transmit_period_callback(dev, dev->sd->priv, dev->transmit_period);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@@ -161,7 +163,7 @@ write_fifo(serial_t *dev, uint8_t dat)
|
|||||||
dev->lsr |= 0x01;
|
dev->lsr |= 0x01;
|
||||||
dev->int_status |= SERIAL_INT_RECEIVE;
|
dev->int_status |= SERIAL_INT_RECEIVE;
|
||||||
}
|
}
|
||||||
if (dev->rcvr_fifo_pos < 15)
|
if (dev->rcvr_fifo_pos < (dev->rcvr_fifo_len - 1))
|
||||||
dev->rcvr_fifo_pos++;
|
dev->rcvr_fifo_pos++;
|
||||||
else
|
else
|
||||||
dev->rcvr_fifo_full = 1;
|
dev->rcvr_fifo_full = 1;
|
||||||
@@ -175,6 +177,8 @@ write_fifo(serial_t *dev, uint8_t dat)
|
|||||||
dev->dat = dat;
|
dev->dat = dat;
|
||||||
dev->lsr |= 0x01;
|
dev->lsr |= 0x01;
|
||||||
dev->int_status |= SERIAL_INT_RECEIVE;
|
dev->int_status |= SERIAL_INT_RECEIVE;
|
||||||
|
if (dev->lsr & 0x02)
|
||||||
|
dev->int_status |= SERIAL_INT_LSR;
|
||||||
serial_update_ints(dev);
|
serial_update_ints(dev);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -311,6 +315,22 @@ serial_timeout_timer(void *priv)
|
|||||||
serial_update_ints(dev);
|
serial_update_ints(dev);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
serial_device_timeout(void *priv)
|
||||||
|
{
|
||||||
|
serial_t *dev = (serial_t *) priv;
|
||||||
|
|
||||||
|
#ifdef ENABLE_SERIAL_LOG
|
||||||
|
serial_log("serial_device_timeout()\n");
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (!dev->fifo_enabled) {
|
||||||
|
dev->lsr |= 0x10;
|
||||||
|
dev->int_status |= SERIAL_INT_LSR;
|
||||||
|
serial_update_ints(dev);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
serial_update_speed(serial_t *dev)
|
serial_update_speed(serial_t *dev)
|
||||||
{
|
{
|
||||||
@@ -331,6 +351,63 @@ serial_reset_fifo(serial_t *dev)
|
|||||||
dev->rcvr_fifo_full = 0;
|
dev->rcvr_fifo_full = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
serial_set_dsr(serial_t *dev, uint8_t enabled)
|
||||||
|
{
|
||||||
|
if (dev->mctrl & 0x10)
|
||||||
|
return;
|
||||||
|
|
||||||
|
dev->msr &= ~0x2;
|
||||||
|
dev->msr |= !!((dev->msr & 0x20) ^ (enabled << 5)) << 1;
|
||||||
|
dev->msr &= ~0x20;
|
||||||
|
dev->msr |= (!!enabled) << 5;
|
||||||
|
dev->msr_set &= ~0x20;
|
||||||
|
dev->msr_set |= (!!enabled) << 5;
|
||||||
|
|
||||||
|
if (dev->msr & 0x2) {
|
||||||
|
dev->int_status |= SERIAL_INT_MSR;
|
||||||
|
serial_update_ints(dev);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
serial_set_cts(serial_t *dev, uint8_t enabled)
|
||||||
|
{
|
||||||
|
if (dev->mctrl & 0x10)
|
||||||
|
return;
|
||||||
|
|
||||||
|
dev->msr &= ~0x1;
|
||||||
|
dev->msr |= !!((dev->msr & 0x10) ^ (enabled << 4));
|
||||||
|
dev->msr &= ~0x10;
|
||||||
|
dev->msr |= (!!enabled) << 4;
|
||||||
|
dev->msr_set &= ~0x10;
|
||||||
|
dev->msr_set |= (!!enabled) << 4;
|
||||||
|
|
||||||
|
if (dev->msr & 0x1) {
|
||||||
|
dev->int_status |= SERIAL_INT_MSR;
|
||||||
|
serial_update_ints(dev);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
serial_set_dcd(serial_t *dev, uint8_t enabled)
|
||||||
|
{
|
||||||
|
if (dev->mctrl & 0x10)
|
||||||
|
return;
|
||||||
|
|
||||||
|
dev->msr &= ~0x8;
|
||||||
|
dev->msr |= !!((dev->msr & 0x80) ^ (enabled << 7));
|
||||||
|
dev->msr &= ~0x80;
|
||||||
|
dev->msr |= (!!enabled) << 7;
|
||||||
|
dev->msr_set &= ~0x80;
|
||||||
|
dev->msr_set |= (!!enabled) << 7;
|
||||||
|
|
||||||
|
if (dev->msr & 0x8) {
|
||||||
|
dev->int_status |= SERIAL_INT_MSR;
|
||||||
|
serial_update_ints(dev);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
serial_set_clock_src(serial_t *dev, double clock_src)
|
serial_set_clock_src(serial_t *dev, double clock_src)
|
||||||
{
|
{
|
||||||
@@ -431,7 +508,7 @@ serial_write(uint16_t addr, uint8_t val, void *p)
|
|||||||
case 3:
|
case 3:
|
||||||
old = dev->lcr;
|
old = dev->lcr;
|
||||||
dev->lcr = val;
|
dev->lcr = val;
|
||||||
if ((old ^ val) & 0x0f) {
|
if ((old ^ val) & 0x3f) {
|
||||||
/* Data bits + start bit. */
|
/* Data bits + start bit. */
|
||||||
dev->bits = ((dev->lcr & 0x03) + 5) + 1;
|
dev->bits = ((dev->lcr & 0x03) + 5) + 1;
|
||||||
/* Stop bits. */
|
/* Stop bits. */
|
||||||
@@ -444,11 +521,14 @@ serial_write(uint16_t addr, uint8_t val, void *p)
|
|||||||
|
|
||||||
serial_transmit_period(dev);
|
serial_transmit_period(dev);
|
||||||
serial_update_speed(dev);
|
serial_update_speed(dev);
|
||||||
|
|
||||||
|
if (dev->sd && dev->sd->lcr_callback)
|
||||||
|
dev->sd->lcr_callback(dev, dev->sd->priv, dev->lcr);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 4:
|
case 4:
|
||||||
if ((val & 2) && !(dev->mctrl & 2)) {
|
if ((val & 2) && !(dev->mctrl & 2)) {
|
||||||
if (dev->sd->rcr_callback)
|
if (dev->sd && dev->sd->rcr_callback)
|
||||||
dev->sd->rcr_callback(dev, dev->sd->priv);
|
dev->sd->rcr_callback(dev, dev->sd->priv);
|
||||||
}
|
}
|
||||||
if (!(val & 8) && (dev->mctrl & 8))
|
if (!(val & 8) && (dev->mctrl & 8))
|
||||||
@@ -487,7 +567,7 @@ serial_write(uint16_t addr, uint8_t val, void *p)
|
|||||||
serial_update_ints(dev);
|
serial_update_ints(dev);
|
||||||
break;
|
break;
|
||||||
case 6:
|
case 6:
|
||||||
dev->msr = val;
|
dev->msr = (val & 0xF0) | (dev->msr & 0x0F);
|
||||||
if (dev->msr & 0x0f)
|
if (dev->msr & 0x0f)
|
||||||
dev->int_status |= SERIAL_INT_MSR;
|
dev->int_status |= SERIAL_INT_MSR;
|
||||||
serial_update_ints(dev);
|
serial_update_ints(dev);
|
||||||
@@ -521,11 +601,15 @@ serial_read(uint16_t addr, void *p)
|
|||||||
|
|
||||||
ret = dev->rcvr_fifo[0];
|
ret = dev->rcvr_fifo[0];
|
||||||
dev->rcvr_fifo_full = 0;
|
dev->rcvr_fifo_full = 0;
|
||||||
if (dev->rcvr_fifo_pos > 0) {
|
|
||||||
for (i = 1; i < 16; i++)
|
for (i = 1; i < 16; i++)
|
||||||
dev->rcvr_fifo[i - 1] = dev->rcvr_fifo[i];
|
dev->rcvr_fifo[i - 1] = dev->rcvr_fifo[i];
|
||||||
serial_log("FIFO position %i: read %02X, next %02X\n", dev->rcvr_fifo_pos, ret, dev->rcvr_fifo[0]);
|
|
||||||
dev->rcvr_fifo_pos--;
|
dev->rcvr_fifo_pos--;
|
||||||
|
|
||||||
|
if (dev->rcvr_fifo_pos > 0) {
|
||||||
|
serial_log("FIFO position %i: read %02X, next %02X\n", dev->rcvr_fifo_pos, ret, dev->rcvr_fifo[0]);
|
||||||
|
|
||||||
/* At least one byte remains to be read, start the timeout
|
/* At least one byte remains to be read, start the timeout
|
||||||
timer so that a timeout is indicated in case of no read. */
|
timer so that a timeout is indicated in case of no read. */
|
||||||
timer_on_auto(&dev->timeout_timer, 4.0 * dev->bits * dev->transmit_period);
|
timer_on_auto(&dev->timeout_timer, 4.0 * dev->bits * dev->transmit_period);
|
||||||
@@ -571,7 +655,7 @@ serial_read(uint16_t addr, void *p)
|
|||||||
serial_update_ints(dev);
|
serial_update_ints(dev);
|
||||||
break;
|
break;
|
||||||
case 6:
|
case 6:
|
||||||
ret = dev->msr;
|
ret = dev->msr | dev->msr_set;
|
||||||
dev->msr &= ~0x0f;
|
dev->msr &= ~0x0f;
|
||||||
dev->int_status &= ~SERIAL_INT_MSR;
|
dev->int_status &= ~SERIAL_INT_MSR;
|
||||||
serial_update_ints(dev);
|
serial_update_ints(dev);
|
||||||
@@ -632,6 +716,27 @@ serial_attach(int port,
|
|||||||
|
|
||||||
sd->rcr_callback = rcr_callback;
|
sd->rcr_callback = rcr_callback;
|
||||||
sd->dev_write = dev_write;
|
sd->dev_write = dev_write;
|
||||||
|
sd->transmit_period_callback = NULL;
|
||||||
|
sd->lcr_callback = NULL;
|
||||||
|
sd->priv = priv;
|
||||||
|
|
||||||
|
return sd->serial;
|
||||||
|
}
|
||||||
|
|
||||||
|
serial_t *
|
||||||
|
serial_attach_ex(int port,
|
||||||
|
void (*rcr_callback)(struct serial_s *serial, void *p),
|
||||||
|
void (*dev_write)(struct serial_s *serial, void *p, uint8_t data),
|
||||||
|
void (*transmit_period_callback)(struct serial_s *serial, void *p, double transmit_period),
|
||||||
|
void (*lcr_callback)(struct serial_s *serial, void *p, uint8_t data_bits),
|
||||||
|
void *priv)
|
||||||
|
{
|
||||||
|
serial_device_t *sd = &serial_devices[port];
|
||||||
|
|
||||||
|
sd->rcr_callback = rcr_callback;
|
||||||
|
sd->dev_write = dev_write;
|
||||||
|
sd->transmit_period_callback = transmit_period_callback;
|
||||||
|
sd->lcr_callback = lcr_callback;
|
||||||
sd->priv = priv;
|
sd->priv = priv;
|
||||||
|
|
||||||
return sd->serial;
|
return sd->serial;
|
||||||
|
|||||||
357
src/device/serial_passthrough.c
Normal file
357
src/device/serial_passthrough.c
Normal file
@@ -0,0 +1,357 @@
|
|||||||
|
/*
|
||||||
|
* 86Box A hypervisor and IBM PC system emulator that specializes in
|
||||||
|
* running old operating systems and software designed for IBM
|
||||||
|
* PC systems and compatibles from 1981 through fairly recent
|
||||||
|
* system designs based on the PCI bus.
|
||||||
|
*
|
||||||
|
* This file is part of the 86Box distribution.
|
||||||
|
*
|
||||||
|
* Implementation of Serial passthrough device.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* Authors: Andreas J. Reichel <webmaster@6th-dimension.com>,
|
||||||
|
* Jasmine Iwanek <jasmine@iwanek.co.uk>
|
||||||
|
*
|
||||||
|
* Copyright 2021 Andreas J. Reichel.
|
||||||
|
* Copyright 2021-2022 Jasmine Iwanek.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <wchar.h>
|
||||||
|
#define HAVE_STDARG_H
|
||||||
|
#include <86box/86box.h>
|
||||||
|
#include <86box/device.h>
|
||||||
|
#include <86box/timer.h>
|
||||||
|
#include <86box/serial.h>
|
||||||
|
#include <86box/serial_passthrough.h>
|
||||||
|
#include <86box/plat_serial_passthrough.h>
|
||||||
|
|
||||||
|
#define ENABLE_SERIAL_PASSTHROUGH_LOG 1
|
||||||
|
#ifdef ENABLE_SERIAL_PASSTHROUGH_LOG
|
||||||
|
int serial_passthrough_do_log = ENABLE_SERIAL_PASSTHROUGH_LOG;
|
||||||
|
|
||||||
|
static void
|
||||||
|
serial_passthrough_log(const char *fmt, ...)
|
||||||
|
{
|
||||||
|
va_list ap;
|
||||||
|
|
||||||
|
if (serial_passthrough_do_log) {
|
||||||
|
va_start(ap, fmt);
|
||||||
|
pclog_ex(fmt, ap);
|
||||||
|
va_end(ap);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
# define serial_passthrough_log(fmt, ...)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void
|
||||||
|
serial_passthrough_init(void)
|
||||||
|
{
|
||||||
|
int c;
|
||||||
|
|
||||||
|
for (c = 0; c < SERIAL_MAX; c++) {
|
||||||
|
if (serial_passthrough_enabled[c]) {
|
||||||
|
/* Instance n for COM n */
|
||||||
|
device_add_inst(&serial_passthrough_device, c + 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
serial_passthrough_timers_off(serial_passthrough_t *dev)
|
||||||
|
{
|
||||||
|
timer_stop(&dev->host_to_serial_timer);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
serial_passthrough_write(serial_t *s, void *priv, uint8_t val)
|
||||||
|
{
|
||||||
|
plat_serpt_write(priv, val);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
host_to_serial_cb(void *priv)
|
||||||
|
{
|
||||||
|
serial_passthrough_t *dev = (serial_passthrough_t *) priv;
|
||||||
|
|
||||||
|
uint8_t byte;
|
||||||
|
|
||||||
|
/* 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
|
||||||
|
* fifo mode or if lsr has bit 0 set if not in fifo mode */
|
||||||
|
if ((dev->serial->type >= SERIAL_16550) && dev->serial->fifo_enabled) {
|
||||||
|
if (dev->serial->rcvr_fifo_full) {
|
||||||
|
goto no_write_to_machine;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (dev->serial->lsr & 1) {
|
||||||
|
goto no_write_to_machine;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (plat_serpt_read(dev, &byte)) {
|
||||||
|
// printf("got byte %02X\n", byte);
|
||||||
|
serial_write_fifo(dev->serial, byte);
|
||||||
|
// serial_set_dsr(dev->serial, 1);
|
||||||
|
}
|
||||||
|
no_write_to_machine:
|
||||||
|
// serial_device_timeout(dev->serial);
|
||||||
|
timer_on_auto(&dev->host_to_serial_timer, (1000000.0 / dev->baudrate) * (double) dev->bits);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
serial_passthrough_rcr_cb(struct serial_s *serial, void *priv)
|
||||||
|
{
|
||||||
|
serial_passthrough_t *dev = (serial_passthrough_t *) priv;
|
||||||
|
|
||||||
|
timer_stop(&dev->host_to_serial_timer);
|
||||||
|
/* FIXME: do something to dev->baudrate */
|
||||||
|
timer_on_auto(&dev->host_to_serial_timer, (1000000.0 / dev->baudrate) * (double) dev->bits);
|
||||||
|
// serial_clear_fifo(dev->serial);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
serial_passthrough_speed_changed(void *priv)
|
||||||
|
{
|
||||||
|
serial_passthrough_t *dev = (serial_passthrough_t *) priv;
|
||||||
|
|
||||||
|
timer_stop(&dev->host_to_serial_timer);
|
||||||
|
/* FIXME: do something to dev->baudrate */
|
||||||
|
timer_on_auto(&dev->host_to_serial_timer, (1000000.0 / dev->baudrate) * (double) dev->bits);
|
||||||
|
// serial_clear_fifo(dev->serial);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
serial_passthrough_dev_close(void *priv)
|
||||||
|
{
|
||||||
|
serial_passthrough_t *dev = (serial_passthrough_t *) priv;
|
||||||
|
|
||||||
|
/* Detach passthrough device from COM port */
|
||||||
|
if (dev && dev->serial && dev->serial->sd)
|
||||||
|
memset(dev->serial->sd, 0, sizeof(serial_device_t));
|
||||||
|
|
||||||
|
plat_serpt_close(dev);
|
||||||
|
free(dev);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
serial_passthrough_transmit_period(serial_t *serial, void *p, double transmit_period)
|
||||||
|
{
|
||||||
|
serial_passthrough_t *dev = (serial_passthrough_t *) p;
|
||||||
|
|
||||||
|
if (dev->mode != SERPT_MODE_HOSTSER)
|
||||||
|
return;
|
||||||
|
dev->baudrate = 1000000.0 / (transmit_period);
|
||||||
|
|
||||||
|
serial_passthrough_speed_changed(p);
|
||||||
|
plat_serpt_set_params(dev);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
serial_passthrough_lcr_callback(serial_t *serial, void *p, uint8_t lcr)
|
||||||
|
{
|
||||||
|
serial_passthrough_t *dev = (serial_passthrough_t *) p;
|
||||||
|
|
||||||
|
if (dev->mode != SERPT_MODE_HOSTSER)
|
||||||
|
return;
|
||||||
|
dev->bits = serial->bits;
|
||||||
|
dev->data_bits = ((lcr & 0x03) + 5);
|
||||||
|
serial_passthrough_speed_changed(p);
|
||||||
|
plat_serpt_set_params(dev);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Initialize the device for use by the user. */
|
||||||
|
static void *
|
||||||
|
serial_passthrough_dev_init(const device_t *info)
|
||||||
|
{
|
||||||
|
serial_passthrough_t *dev;
|
||||||
|
|
||||||
|
dev = (serial_passthrough_t *) malloc(sizeof(serial_passthrough_t));
|
||||||
|
memset(dev, 0, sizeof(serial_passthrough_t));
|
||||||
|
dev->mode = device_get_config_int("mode");
|
||||||
|
|
||||||
|
dev->port = device_get_instance() - 1;
|
||||||
|
dev->baudrate = device_get_config_int("baudrate");
|
||||||
|
dev->data_bits = device_get_config_int("data_bits");
|
||||||
|
|
||||||
|
/* Attach passthrough device to a COM port */
|
||||||
|
dev->serial = serial_attach_ex(dev->port, serial_passthrough_rcr_cb,
|
||||||
|
serial_passthrough_write, serial_passthrough_transmit_period, serial_passthrough_lcr_callback, dev);
|
||||||
|
|
||||||
|
strncpy(dev->host_serial_path, device_get_config_string("host_serial_path"), 1024);
|
||||||
|
|
||||||
|
serial_passthrough_log("%s: port=COM%d\n", info->name, dev->port + 1);
|
||||||
|
serial_passthrough_log("%s: baud=%f\n", info->name, dev->baudrate);
|
||||||
|
serial_passthrough_log("%s: mode=%s\n", info->name, serpt_mode_names[dev->mode]);
|
||||||
|
|
||||||
|
if (plat_serpt_open_device(dev)) {
|
||||||
|
serial_passthrough_log("%s: not running\n", info->name);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
serial_passthrough_log("%s: running\n", info->name);
|
||||||
|
|
||||||
|
memset(&dev->host_to_serial_timer, 0, sizeof(pc_timer_t));
|
||||||
|
timer_add(&dev->host_to_serial_timer, host_to_serial_cb, dev, 1);
|
||||||
|
serial_set_cts(dev->serial, 1);
|
||||||
|
serial_set_dsr(dev->serial, 1);
|
||||||
|
serial_set_dcd(dev->serial, 1);
|
||||||
|
|
||||||
|
/* 1 start bit + data bits + stop bits (no parity assumed) */
|
||||||
|
dev->bits = 1 + device_get_config_int("data_bits") + device_get_config_int("stop_bits");
|
||||||
|
|
||||||
|
/* Return our private data to the I/O layer. */
|
||||||
|
return dev;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *serpt_mode_names[SERPT_MODES_MAX] = {
|
||||||
|
[SERPT_MODE_VCON] = "vcon",
|
||||||
|
[SERPT_MODE_TCPSRV] = "tcpsrv",
|
||||||
|
[SERPT_MODE_TCPCLNT] = "tcpclnt",
|
||||||
|
[SERPT_MODE_HOSTSER] = "hostser",
|
||||||
|
};
|
||||||
|
|
||||||
|
// clang-format off
|
||||||
|
static const device_config_t serial_passthrough_config[] = {
|
||||||
|
{
|
||||||
|
.name = "mode",
|
||||||
|
.description = "Passthrough Mode",
|
||||||
|
.type = CONFIG_SELECTION,
|
||||||
|
.default_string = "",
|
||||||
|
.default_int = 0,
|
||||||
|
.file_filter = "",
|
||||||
|
.spinner = { 0 },
|
||||||
|
.selection = {
|
||||||
|
#ifdef _WIN32
|
||||||
|
{
|
||||||
|
.description = "Named Pipe (Server)",
|
||||||
|
.value = SERPT_MODE_VCON
|
||||||
|
},
|
||||||
|
#if 0 /* TODO */
|
||||||
|
{
|
||||||
|
.description = "Named Pipe (Client)",
|
||||||
|
.value = SERPT_MODE_VCON
|
||||||
|
},
|
||||||
|
#endif
|
||||||
|
#else
|
||||||
|
{
|
||||||
|
.description = "Pseudo Terminal/Virtual Console",
|
||||||
|
.value = SERPT_MODE_VCON
|
||||||
|
},
|
||||||
|
#endif
|
||||||
|
#if 0 /* TODO */
|
||||||
|
{
|
||||||
|
.description = "TCP Server",
|
||||||
|
.value = SERPT_MODE_TCPSRV
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.description = "TCP Client",
|
||||||
|
.value = SERPT_MODE_TCPCLNT
|
||||||
|
},
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
.description = "Host Serial Passthrough",
|
||||||
|
.value = SERPT_MODE_HOSTSER
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.description = ""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.name = "host_serial_path",
|
||||||
|
.description = "Host Serial Device",
|
||||||
|
.type = CONFIG_SERPORT,
|
||||||
|
.default_string = "",
|
||||||
|
.file_filter = NULL,
|
||||||
|
.spinner = {},
|
||||||
|
.selection = {}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.name = "data_bits",
|
||||||
|
.description = "Data bits",
|
||||||
|
.type = CONFIG_SELECTION,
|
||||||
|
.default_string = "8",
|
||||||
|
.default_int = 8,
|
||||||
|
.file_filter = NULL,
|
||||||
|
.spinner = { 0 },
|
||||||
|
.selection = {
|
||||||
|
#if 0 /* Mentioned by WFW 3.1x, not supported, atleast on Linux */
|
||||||
|
{ .description = "4", .value = 4 },
|
||||||
|
#endif
|
||||||
|
{ .description = "5", .value = 5 },
|
||||||
|
{ .description = "6", .value = 6 },
|
||||||
|
{ .description = "7", .value = 7 },
|
||||||
|
{ .description = "8", .value = 8 }
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.name = "stop_bits",
|
||||||
|
.description = "Stop bits",
|
||||||
|
.type = CONFIG_SELECTION,
|
||||||
|
.default_string = "1",
|
||||||
|
.default_int = 1,
|
||||||
|
.file_filter = NULL,
|
||||||
|
.spinner = { 0 },
|
||||||
|
.selection = {
|
||||||
|
{ .description = "1", .value = 1 },
|
||||||
|
#if 0
|
||||||
|
{ .description = "1.5", .value = 1.5 },
|
||||||
|
#endif
|
||||||
|
{ .description = "2", .value = 2 }
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.name = "baudrate",
|
||||||
|
.description = "Baud Rate of Passthrough",
|
||||||
|
.type = CONFIG_SELECTION,
|
||||||
|
.default_string = "",
|
||||||
|
.default_int = 115200,
|
||||||
|
.file_filter = NULL,
|
||||||
|
.spinner = { 0 },
|
||||||
|
.selection = {
|
||||||
|
#if 0
|
||||||
|
{ .description = "256000", .value = 256000 },
|
||||||
|
{ .description = "128000", .value = 128000 },
|
||||||
|
#endif
|
||||||
|
{ .description = "115200", .value = 115200 },
|
||||||
|
{ .description = "57600", .value = 57600 },
|
||||||
|
{ .description = "56000", .value = 56000 },
|
||||||
|
{ .description = "38400", .value = 38400 },
|
||||||
|
{ .description = "19200", .value = 19200 },
|
||||||
|
{ .description = "14400", .value = 14400 },
|
||||||
|
{ .description = "9600", .value = 9600 },
|
||||||
|
{ .description = "7200", .value = 7200 },
|
||||||
|
{ .description = "4800", .value = 4800 },
|
||||||
|
{ .description = "2400", .value = 2400 },
|
||||||
|
{ .description = "1800", .value = 1800 },
|
||||||
|
{ .description = "1200", .value = 1200 },
|
||||||
|
{ .description = "600", .value = 600 },
|
||||||
|
{ .description = "300", .value = 300 },
|
||||||
|
{ .description = "150", .value = 150 },
|
||||||
|
#if 0
|
||||||
|
{ .description = "134.5", .value = 134.5 },
|
||||||
|
#endif
|
||||||
|
{ .description = "110", .value = 110 },
|
||||||
|
{ .description = "75", .value = 75 }
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{ .name = "", .description = "", .type = CONFIG_END }
|
||||||
|
};
|
||||||
|
// clang-format on
|
||||||
|
|
||||||
|
const device_t serial_passthrough_device = {
|
||||||
|
.name = "Serial Passthrough Device",
|
||||||
|
.flags = 0,
|
||||||
|
.local = 0,
|
||||||
|
.init = serial_passthrough_dev_init,
|
||||||
|
.close = serial_passthrough_dev_close,
|
||||||
|
.reset = NULL,
|
||||||
|
{ .poll = NULL },
|
||||||
|
.speed_changed = serial_passthrough_speed_changed,
|
||||||
|
.force_redraw = NULL,
|
||||||
|
.config = serial_passthrough_config
|
||||||
|
};
|
||||||
@@ -17,6 +17,8 @@
|
|||||||
* Copyright 2017-2019 Fred N. van Kempen.
|
* Copyright 2017-2019 Fred N. van Kempen.
|
||||||
* Copyright 2016-2019 Miran Grca.
|
* Copyright 2016-2019 Miran Grca.
|
||||||
* Copyright 2008-2019 Sarah Walker.
|
* Copyright 2008-2019 Sarah Walker.
|
||||||
|
* Copyright 2021 Andreas J. Reichel.
|
||||||
|
* Copyright 2021-2022 Jasmine Iwanek.
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* This program is free software; you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
@@ -52,6 +54,7 @@
|
|||||||
#define CONFIG_MAC 9
|
#define CONFIG_MAC 9
|
||||||
#define CONFIG_MIDI_IN 10
|
#define CONFIG_MIDI_IN 10
|
||||||
#define CONFIG_BIOS 11
|
#define CONFIG_BIOS 11
|
||||||
|
#define CONFIG_SERPORT 12
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
DEVICE_PCJR = 2, /* requires an IBM PCjr */
|
DEVICE_PCJR = 2, /* requires an IBM PCjr */
|
||||||
@@ -107,7 +110,7 @@ typedef struct {
|
|||||||
int default_int;
|
int default_int;
|
||||||
const char *file_filter;
|
const char *file_filter;
|
||||||
const device_config_spinner_t spinner;
|
const device_config_spinner_t spinner;
|
||||||
const device_config_selection_t selection[16];
|
const device_config_selection_t selection[32];
|
||||||
const device_config_bios_t bios[32];
|
const device_config_bios_t bios[32];
|
||||||
} device_config_t;
|
} device_config_t;
|
||||||
|
|
||||||
@@ -134,6 +137,7 @@ typedef struct _device_ {
|
|||||||
typedef struct {
|
typedef struct {
|
||||||
const device_t *dev;
|
const device_t *dev;
|
||||||
char name[2048];
|
char name[2048];
|
||||||
|
int instance;
|
||||||
} device_context_t;
|
} device_context_t;
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
@@ -178,6 +182,7 @@ extern void device_set_config_hex16(const char *s, int val);
|
|||||||
extern void device_set_config_hex20(const char *s, int val);
|
extern void device_set_config_hex20(const char *s, int val);
|
||||||
extern void device_set_config_mac(const char *s, int val);
|
extern void device_set_config_mac(const char *s, int val);
|
||||||
extern const char *device_get_config_string(const char *name);
|
extern const char *device_get_config_string(const char *name);
|
||||||
|
extern const int device_get_instance(void);
|
||||||
#define device_get_config_bios device_get_config_string
|
#define device_get_config_bios device_get_config_string
|
||||||
|
|
||||||
extern char *device_get_internal_name(const device_t *d);
|
extern char *device_get_internal_name(const device_t *d);
|
||||||
|
|||||||
38
src/include/86box/plat_serial_passthrough.h
Normal file
38
src/include/86box/plat_serial_passthrough.h
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
/*
|
||||||
|
* 86Box A hypervisor and IBM PC system emulator that specializes in
|
||||||
|
* running old operating systems and software designed for IBM
|
||||||
|
* PC systems and compatibles from 1981 through fairly recent
|
||||||
|
* system designs based on the PCI bus.
|
||||||
|
*
|
||||||
|
* This file is part of the 86Box distribution.
|
||||||
|
*
|
||||||
|
* Definitions for platform specific serial to host passthrough.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* Authors: Andreas J. Reichel <webmaster@6th-dimension.com>,
|
||||||
|
* Jasmine Iwanek <jasmine@iwanek.co.uk>
|
||||||
|
*
|
||||||
|
* Copyright 2021 Andreas J. Reichel.
|
||||||
|
* Copyright 2021-2022 Jasmine Iwanek.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef PLAT_SERIAL_PASSTHROUGH_H
|
||||||
|
#define PLAT_SERIAL_PASSTHROUGH_H
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
extern void plat_serpt_write(void *p, uint8_t data);
|
||||||
|
extern int plat_serpt_read(void *p, uint8_t *data);
|
||||||
|
extern int plat_serpt_open_device(void *p);
|
||||||
|
extern void plat_serpt_close(void *p);
|
||||||
|
extern void plat_serpt_set_params(void *p);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -247,6 +247,10 @@
|
|||||||
#define IDC_CHECK_PARALLEL2 1089
|
#define IDC_CHECK_PARALLEL2 1089
|
||||||
#define IDC_CHECK_PARALLEL3 1090
|
#define IDC_CHECK_PARALLEL3 1090
|
||||||
#define IDC_CHECK_PARALLEL4 1091
|
#define IDC_CHECK_PARALLEL4 1091
|
||||||
|
#define IDC_CHECK_SERIAL_PASS1 1092
|
||||||
|
#define IDC_CHECK_SERIAL_PASS2 1093
|
||||||
|
#define IDC_CHECK_SERIAL_PASS3 1094
|
||||||
|
#define IDC_CHECK_SERIAL_PASS4 1095
|
||||||
|
|
||||||
#define IDC_OTHER_PERIPH 1110 /* storage controllers config */
|
#define IDC_OTHER_PERIPH 1110 /* storage controllers config */
|
||||||
#define IDC_COMBO_HDC 1111
|
#define IDC_COMBO_HDC 1111
|
||||||
@@ -364,6 +368,10 @@
|
|||||||
#define IDC_CONFIGURE_NET4 1321
|
#define IDC_CONFIGURE_NET4 1321
|
||||||
#define IDC_CONFIGURE_MIDI_OUT 1322
|
#define IDC_CONFIGURE_MIDI_OUT 1322
|
||||||
#define IDC_CONFIGURE_MIDI_IN 1323
|
#define IDC_CONFIGURE_MIDI_IN 1323
|
||||||
|
#define IDC_CONFIGURE_SERIAL_PASS1 1324
|
||||||
|
#define IDC_CONFIGURE_SERIAL_PASS2 1325
|
||||||
|
#define IDC_CONFIGURE_SERIAL_PASS3 1326
|
||||||
|
#define IDC_CONFIGURE_SERIAL_PASS4 1327
|
||||||
#define IDC_JOY1 1330
|
#define IDC_JOY1 1330
|
||||||
#define IDC_JOY2 1331
|
#define IDC_JOY2 1331
|
||||||
#define IDC_JOY3 1332
|
#define IDC_JOY3 1332
|
||||||
|
|||||||
@@ -53,7 +53,7 @@ typedef struct serial_s {
|
|||||||
dat, int_status, scratch, fcr,
|
dat, int_status, scratch, fcr,
|
||||||
irq, type, inst, transmit_enabled,
|
irq, type, inst, transmit_enabled,
|
||||||
fifo_enabled, rcvr_fifo_len, bits, data_bits,
|
fifo_enabled, rcvr_fifo_len, bits, data_bits,
|
||||||
baud_cycles, rcvr_fifo_full, txsr, pad;
|
baud_cycles, rcvr_fifo_full, txsr, pad, msr_set;
|
||||||
|
|
||||||
uint16_t dlab, base_address;
|
uint16_t dlab, base_address;
|
||||||
|
|
||||||
@@ -70,6 +70,8 @@ typedef struct serial_s {
|
|||||||
typedef struct serial_device_s {
|
typedef struct serial_device_s {
|
||||||
void (*rcr_callback)(struct serial_s *serial, void *p);
|
void (*rcr_callback)(struct serial_s *serial, void *p);
|
||||||
void (*dev_write)(struct serial_s *serial, void *p, uint8_t data);
|
void (*dev_write)(struct serial_s *serial, void *p, uint8_t data);
|
||||||
|
void (*lcr_callback)(struct serial_s *serial, void *p, uint8_t lcr);
|
||||||
|
void (*transmit_period_callback)(struct serial_s *serial, void *p, double transmit_period);
|
||||||
void *priv;
|
void *priv;
|
||||||
serial_t *serial;
|
serial_t *serial;
|
||||||
} serial_device_t;
|
} serial_device_t;
|
||||||
@@ -84,6 +86,12 @@ extern serial_t *serial_attach(int port,
|
|||||||
void (*rcr_callback)(struct serial_s *serial, void *p),
|
void (*rcr_callback)(struct serial_s *serial, void *p),
|
||||||
void (*dev_write)(struct serial_s *serial, void *p, uint8_t data),
|
void (*dev_write)(struct serial_s *serial, void *p, uint8_t data),
|
||||||
void *priv);
|
void *priv);
|
||||||
|
extern serial_t *serial_attach_ex(int port,
|
||||||
|
void (*rcr_callback)(struct serial_s *serial, void *p),
|
||||||
|
void (*dev_write)(struct serial_s *serial, void *p, uint8_t data),
|
||||||
|
void (*transmit_period_callback)(struct serial_s *serial, void *p, double transmit_period),
|
||||||
|
void (*lcr_callback)(struct serial_s *serial, void *p, uint8_t data_bits),
|
||||||
|
void *priv);
|
||||||
extern void serial_remove(serial_t *dev);
|
extern void serial_remove(serial_t *dev);
|
||||||
extern void serial_set_type(serial_t *dev, int type);
|
extern void serial_set_type(serial_t *dev, int type);
|
||||||
extern void serial_setup(serial_t *dev, uint16_t addr, uint8_t irq);
|
extern void serial_setup(serial_t *dev, uint16_t addr, uint8_t irq);
|
||||||
@@ -93,6 +101,11 @@ extern void serial_set_next_inst(int ni);
|
|||||||
extern void serial_standalone_init(void);
|
extern void serial_standalone_init(void);
|
||||||
extern void serial_set_clock_src(serial_t *dev, double clock_src);
|
extern void serial_set_clock_src(serial_t *dev, double clock_src);
|
||||||
extern void serial_reset_port(serial_t *dev);
|
extern void serial_reset_port(serial_t *dev);
|
||||||
|
extern void serial_device_timeout(void *priv);
|
||||||
|
|
||||||
|
extern void serial_set_cts(serial_t *dev, uint8_t enabled);
|
||||||
|
extern void serial_set_dsr(serial_t *dev, uint8_t enabled);
|
||||||
|
extern void serial_set_dcd(serial_t *dev, uint8_t enabled);
|
||||||
|
|
||||||
extern const device_t ns8250_device;
|
extern const device_t ns8250_device;
|
||||||
extern const device_t ns8250_pcjr_device;
|
extern const device_t ns8250_pcjr_device;
|
||||||
|
|||||||
61
src/include/86box/serial_passthrough.h
Normal file
61
src/include/86box/serial_passthrough.h
Normal file
@@ -0,0 +1,61 @@
|
|||||||
|
/*
|
||||||
|
* 86Box A hypervisor and IBM PC system emulator that specializes in
|
||||||
|
* running old operating systems and software designed for IBM
|
||||||
|
* PC systems and compatibles from 1981 through fairly recent
|
||||||
|
* system designs based on the PCI bus.
|
||||||
|
*
|
||||||
|
* This file is part of the 86Box distribution.
|
||||||
|
*
|
||||||
|
* Definition of Serial passthrough device.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* Authors: Andreas J. Reichel <webmaster@6th-dimension.com>,
|
||||||
|
* Jasmine Iwanek <jasmine@iwanek.co.uk>
|
||||||
|
*
|
||||||
|
* Copyright 2021 Andreas J. Reichel.
|
||||||
|
* Copyright 2021-2022 Jasmine Iwanek.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef SERIAL_PASSTHROUGH_H
|
||||||
|
#define SERIAL_PASSTHROUGH_H
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
|
#include <86box/86box.h>
|
||||||
|
#include <86box/device.h>
|
||||||
|
#include <86box/timer.h>
|
||||||
|
#include <86box/serial.h>
|
||||||
|
|
||||||
|
enum serial_passthrough_mode {
|
||||||
|
SERPT_MODE_VCON, /*Named Pipe (Server) / Pseudo Terminal/Virtual Console */
|
||||||
|
SERPT_MODE_TCPSRV, /* TCP Server (TODO) */
|
||||||
|
SERPT_MODE_TCPCLNT, /* TCP Client (TODO) */
|
||||||
|
SERPT_MODE_HOSTSER, /* Host Serial Passthrough */
|
||||||
|
SERPT_MODES_MAX,
|
||||||
|
};
|
||||||
|
|
||||||
|
extern const char *serpt_mode_names[SERPT_MODES_MAX];
|
||||||
|
|
||||||
|
typedef struct serial_passthrough_s {
|
||||||
|
enum serial_passthrough_mode mode;
|
||||||
|
pc_timer_t host_to_serial_timer;
|
||||||
|
pc_timer_t serial_to_host_timer;
|
||||||
|
serial_t *serial;
|
||||||
|
double baudrate;
|
||||||
|
uint8_t bits, data_bits;
|
||||||
|
uint8_t port;
|
||||||
|
uint8_t data;
|
||||||
|
char slave_pt[32]; /* used for pseudo term name of slave side */
|
||||||
|
intptr_t master_fd; /* file desc for master pseudo terminal or
|
||||||
|
* socket or alike */
|
||||||
|
char host_serial_path[1024]; /* Path to TTY/host serial port on the host */
|
||||||
|
void *backend_priv; /* Private platform backend data */
|
||||||
|
} serial_passthrough_t;
|
||||||
|
|
||||||
|
extern bool serial_passthrough_enabled[SERIAL_MAX];
|
||||||
|
extern const device_t serial_passthrough_device;
|
||||||
|
|
||||||
|
extern void serial_passthrough_init(void);
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -17,7 +17,7 @@
|
|||||||
#define WIN_OPENGL_H
|
#define WIN_OPENGL_H
|
||||||
|
|
||||||
#define UNICODE
|
#define UNICODE
|
||||||
#include <Windows.h>
|
#include <windows.h>
|
||||||
|
|
||||||
extern int opengl_init(HWND hwnd);
|
extern int opengl_init(HWND hwnd);
|
||||||
extern int opengl_pause(void);
|
extern int opengl_pause(void);
|
||||||
|
|||||||
@@ -9,7 +9,7 @@
|
|||||||
#define _DISCORD_GAME_SDK_H_
|
#define _DISCORD_GAME_SDK_H_
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
#include <Windows.h>
|
#include <windows.h>
|
||||||
#include <dxgi.h>
|
#include <dxgi.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|||||||
@@ -221,6 +221,12 @@ if(WIN32 AND NOT MINGW)
|
|||||||
target_sources(plat PRIVATE ../win/win_opendir.c)
|
target_sources(plat PRIVATE ../win/win_opendir.c)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
if(WIN32)
|
||||||
|
target_sources(plat PRIVATE ../win/win_serial_passthrough.c)
|
||||||
|
else()
|
||||||
|
target_sources(plat PRIVATE ../unix/unix_serial_passthrough.c)
|
||||||
|
endif()
|
||||||
|
|
||||||
if (APPLE)
|
if (APPLE)
|
||||||
target_sources(ui PRIVATE macos_event_filter.mm)
|
target_sources(ui PRIVATE macos_event_filter.mm)
|
||||||
if(MOLTENVK)
|
if(MOLTENVK)
|
||||||
|
|||||||
@@ -27,6 +27,8 @@
|
|||||||
#include <QCheckBox>
|
#include <QCheckBox>
|
||||||
#include <QFrame>
|
#include <QFrame>
|
||||||
#include <QLabel>
|
#include <QLabel>
|
||||||
|
#include <QDir>
|
||||||
|
#include <QSettings>
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#include <86box/86box.h>
|
#include <86box/86box.h>
|
||||||
@@ -40,6 +42,10 @@ extern "C" {
|
|||||||
|
|
||||||
#include "qt_filefield.hpp"
|
#include "qt_filefield.hpp"
|
||||||
#include "qt_models_common.hpp"
|
#include "qt_models_common.hpp"
|
||||||
|
#ifdef Q_OS_LINUX
|
||||||
|
# include <sys/stat.h>
|
||||||
|
# include <sys/sysmacros.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
DeviceConfig::DeviceConfig(QWidget *parent)
|
DeviceConfig::DeviceConfig(QWidget *parent)
|
||||||
: QDialog(parent)
|
: QDialog(parent)
|
||||||
@@ -53,6 +59,40 @@ DeviceConfig::~DeviceConfig()
|
|||||||
delete ui;
|
delete ui;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static QStringList
|
||||||
|
EnumerateSerialDevices()
|
||||||
|
{
|
||||||
|
QStringList serialDevices, ttyEntries;
|
||||||
|
QByteArray devstr(1024, 0);
|
||||||
|
#ifdef Q_OS_LINUX
|
||||||
|
QDir class_dir("/sys/class/tty/");
|
||||||
|
QDir dev_dir("/dev/");
|
||||||
|
ttyEntries = class_dir.entryList(QDir::Dirs | QDir::NoDotAndDotDot | QDir::System, QDir::SortFlag::Name);
|
||||||
|
for (int i = 0; i < ttyEntries.size(); i++) {
|
||||||
|
if (class_dir.exists(ttyEntries[i] + "/device/driver/") && dev_dir.exists(ttyEntries[i])
|
||||||
|
&& QFileInfo(dev_dir.canonicalPath() + '/' + ttyEntries[i]).isReadable()
|
||||||
|
&& QFileInfo(dev_dir.canonicalPath() + '/' + ttyEntries[i]).isWritable()) {
|
||||||
|
serialDevices.push_back("/dev/" + ttyEntries[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#ifdef Q_OS_WINDOWS
|
||||||
|
QSettings comPorts("HKEY_LOCAL_MACHINE\\HARDWARE\\DEVICEMAP\\SERIALCOMM", QSettings::NativeFormat, nullptr);
|
||||||
|
for (int i = 0; i < comPorts.childKeys().length(); i++) {
|
||||||
|
serialDevices.push_back(QString("\\\\.\\") + comPorts.value(comPorts.childKeys()[i]).toString());
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#ifdef Q_OS_MACOS
|
||||||
|
QDir dev_dir("/dev/");
|
||||||
|
dev_dir.setNameFilters({ "tty.*", "cu.*" });
|
||||||
|
QDir::Filters serial_dev_flags = QDir::Files | QDir::NoSymLinks | QDir::Readable | QDir::Writable | QDir::NoDotAndDotDot | QDir::System;
|
||||||
|
for (const auto &device : dev_dir.entryInfoList(serial_dev_flags, QDir::SortFlag::Name)) {
|
||||||
|
serialDevices.push_back(device.canonicalFilePath());
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
return serialDevices;
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
DeviceConfig::ConfigureDevice(const _device_ *device, int instance, Settings *settings)
|
DeviceConfig::ConfigureDevice(const _device_ *device, int instance, Settings *settings)
|
||||||
{
|
{
|
||||||
@@ -205,6 +245,27 @@ DeviceConfig::ConfigureDevice(const _device_ *device, int instance, Settings *se
|
|||||||
dc.ui->formLayout->addRow(config->description, fileField);
|
dc.ui->formLayout->addRow(config->description, fileField);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case CONFIG_SERPORT:
|
||||||
|
{
|
||||||
|
auto *cbox = new QComboBox();
|
||||||
|
cbox->setObjectName(config->name);
|
||||||
|
auto *model = cbox->model();
|
||||||
|
int currentIndex = 0;
|
||||||
|
auto serialDevices = EnumerateSerialDevices();
|
||||||
|
char *selected = config_get_string(device_context.name, const_cast<char *>(config->name), const_cast<char *>(config->default_string));
|
||||||
|
|
||||||
|
Models::AddEntry(model, "None", -1);
|
||||||
|
for (int i = 0; i < serialDevices.size(); i++) {
|
||||||
|
int row = Models::AddEntry(model, serialDevices[i], i);
|
||||||
|
if (selected == serialDevices[i]) {
|
||||||
|
currentIndex = row;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
dc.ui->formLayout->addRow(config->description, cbox);
|
||||||
|
cbox->setCurrentIndex(currentIndex);
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
++config;
|
++config;
|
||||||
}
|
}
|
||||||
@@ -236,6 +297,15 @@ DeviceConfig::ConfigureDevice(const _device_ *device, int instance, Settings *se
|
|||||||
config_set_string(device_context.name, const_cast<char *>(config->name), const_cast<char *>(config->bios[idx].internal_name));
|
config_set_string(device_context.name, const_cast<char *>(config->name), const_cast<char *>(config->bios[idx].internal_name));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case CONFIG_SERPORT:
|
||||||
|
{
|
||||||
|
auto *cbox = dc.findChild<QComboBox *>(config->name);
|
||||||
|
auto path = cbox->currentText().toUtf8();
|
||||||
|
if (path == "None")
|
||||||
|
path = "";
|
||||||
|
config_set_string(device_context.name, const_cast<char *>(config->name), path);
|
||||||
|
break;
|
||||||
|
}
|
||||||
case CONFIG_HEX16:
|
case CONFIG_HEX16:
|
||||||
{
|
{
|
||||||
auto *cbox = dc.findChild<QComboBox *>(config->name);
|
auto *cbox = dc.findChild<QComboBox *>(config->name);
|
||||||
|
|||||||
@@ -43,7 +43,7 @@ Q_IMPORT_PLUGIN(QWindowsVistaStylePlugin)
|
|||||||
# include "qt_winrawinputfilter.hpp"
|
# include "qt_winrawinputfilter.hpp"
|
||||||
# include "qt_winmanagerfilter.hpp"
|
# include "qt_winmanagerfilter.hpp"
|
||||||
# include <86box/win.h>
|
# include <86box/win.h>
|
||||||
# include <Shobjidl.h>
|
# include <shobjidl.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
|
|||||||
@@ -27,6 +27,7 @@ extern "C" {
|
|||||||
#include <86box/machine.h>
|
#include <86box/machine.h>
|
||||||
#include <86box/lpt.h>
|
#include <86box/lpt.h>
|
||||||
#include <86box/serial.h>
|
#include <86box/serial.h>
|
||||||
|
#include <86box/serial_passthrough.h>
|
||||||
}
|
}
|
||||||
|
|
||||||
#include "qt_deviceconfig.hpp"
|
#include "qt_deviceconfig.hpp"
|
||||||
@@ -66,6 +67,15 @@ SettingsPorts::SettingsPorts(QWidget *parent)
|
|||||||
auto *checkBox = findChild<QCheckBox *>(QString("checkBoxSerial%1").arg(i + 1));
|
auto *checkBox = findChild<QCheckBox *>(QString("checkBoxSerial%1").arg(i + 1));
|
||||||
checkBox->setChecked(com_ports[i].enabled > 0);
|
checkBox->setChecked(com_ports[i].enabled > 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ui->checkBoxSerialPassThru1->setChecked(serial_passthrough_enabled[0]);
|
||||||
|
ui->pushButtonSerialPassThru1->setEnabled(serial_passthrough_enabled[0]);
|
||||||
|
ui->checkBoxSerialPassThru2->setChecked(serial_passthrough_enabled[1]);
|
||||||
|
ui->pushButtonSerialPassThru2->setEnabled(serial_passthrough_enabled[1]);
|
||||||
|
ui->checkBoxSerialPassThru3->setChecked(serial_passthrough_enabled[2]);
|
||||||
|
ui->pushButtonSerialPassThru3->setEnabled(serial_passthrough_enabled[2]);
|
||||||
|
ui->checkBoxSerialPassThru4->setChecked(serial_passthrough_enabled[3]);
|
||||||
|
ui->pushButtonSerialPassThru4->setEnabled(serial_passthrough_enabled[3]);
|
||||||
}
|
}
|
||||||
|
|
||||||
SettingsPorts::~SettingsPorts()
|
SettingsPorts::~SettingsPorts()
|
||||||
@@ -87,6 +97,11 @@ SettingsPorts::save()
|
|||||||
auto *checkBox = findChild<QCheckBox *>(QString("checkBoxSerial%1").arg(i + 1));
|
auto *checkBox = findChild<QCheckBox *>(QString("checkBoxSerial%1").arg(i + 1));
|
||||||
com_ports[i].enabled = checkBox->isChecked() ? 1 : 0;
|
com_ports[i].enabled = checkBox->isChecked() ? 1 : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
serial_passthrough_enabled[0] = ui->checkBoxSerialPassThru1->isChecked();
|
||||||
|
serial_passthrough_enabled[1] = ui->checkBoxSerialPassThru2->isChecked();
|
||||||
|
serial_passthrough_enabled[2] = ui->checkBoxSerialPassThru3->isChecked();
|
||||||
|
serial_passthrough_enabled[3] = ui->checkBoxSerialPassThru4->isChecked();
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@@ -112,3 +127,51 @@ SettingsPorts::on_checkBoxParallel4_stateChanged(int state)
|
|||||||
{
|
{
|
||||||
ui->comboBoxLpt4->setEnabled(state == Qt::Checked);
|
ui->comboBoxLpt4->setEnabled(state == Qt::Checked);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
SettingsPorts::on_pushButtonSerialPassThru1_clicked()
|
||||||
|
{
|
||||||
|
DeviceConfig::ConfigureDevice(&serial_passthrough_device, 1, qobject_cast<Settings *>(Settings::settings));
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
SettingsPorts::on_pushButtonSerialPassThru2_clicked()
|
||||||
|
{
|
||||||
|
DeviceConfig::ConfigureDevice(&serial_passthrough_device, 2, qobject_cast<Settings *>(Settings::settings));
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
SettingsPorts::on_pushButtonSerialPassThru3_clicked()
|
||||||
|
{
|
||||||
|
DeviceConfig::ConfigureDevice(&serial_passthrough_device, 3, qobject_cast<Settings *>(Settings::settings));
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
SettingsPorts::on_pushButtonSerialPassThru4_clicked()
|
||||||
|
{
|
||||||
|
DeviceConfig::ConfigureDevice(&serial_passthrough_device, 4, qobject_cast<Settings *>(Settings::settings));
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
SettingsPorts::on_checkBoxSerialPassThru1_clicked(bool checked)
|
||||||
|
{
|
||||||
|
ui->pushButtonSerialPassThru1->setEnabled(checked);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
SettingsPorts::on_checkBoxSerialPassThru2_clicked(bool checked)
|
||||||
|
{
|
||||||
|
ui->pushButtonSerialPassThru2->setEnabled(checked);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
SettingsPorts::on_checkBoxSerialPassThru3_clicked(bool checked)
|
||||||
|
{
|
||||||
|
ui->pushButtonSerialPassThru3->setEnabled(checked);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
SettingsPorts::on_checkBoxSerialPassThru4_clicked(bool checked)
|
||||||
|
{
|
||||||
|
ui->pushButtonSerialPassThru4->setEnabled(checked);
|
||||||
|
}
|
||||||
|
|||||||
@@ -15,6 +15,30 @@ public:
|
|||||||
~SettingsPorts();
|
~SettingsPorts();
|
||||||
|
|
||||||
void save();
|
void save();
|
||||||
|
private slots:
|
||||||
|
void on_checkBoxSerialPassThru4_clicked(bool checked);
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void on_checkBoxSerialPassThru3_clicked(bool checked);
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void on_checkBoxSerialPassThru2_clicked(bool checked);
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void on_pushButtonSerialPassThru4_clicked();
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void on_pushButtonSerialPassThru3_clicked();
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void on_pushButtonSerialPassThru2_clicked();
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void on_pushButtonSerialPassThru1_clicked();
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void on_checkBoxSerialPassThru1_clicked(bool checked);
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void on_checkBoxParallel3_stateChanged(int arg1);
|
void on_checkBoxParallel3_stateChanged(int arg1);
|
||||||
void on_checkBoxParallel2_stateChanged(int arg1);
|
void on_checkBoxParallel2_stateChanged(int arg1);
|
||||||
|
|||||||
@@ -13,7 +13,7 @@
|
|||||||
<property name="windowTitle">
|
<property name="windowTitle">
|
||||||
<string>Form</string>
|
<string>Form</string>
|
||||||
</property>
|
</property>
|
||||||
<layout class="QVBoxLayout" name="verticalLayout">
|
<layout class="QGridLayout" name="gridLayout_4">
|
||||||
<property name="leftMargin">
|
<property name="leftMargin">
|
||||||
<number>0</number>
|
<number>0</number>
|
||||||
</property>
|
</property>
|
||||||
@@ -26,7 +26,7 @@
|
|||||||
<property name="bottomMargin">
|
<property name="bottomMargin">
|
||||||
<number>0</number>
|
<number>0</number>
|
||||||
</property>
|
</property>
|
||||||
<item>
|
<item row="0" column="0">
|
||||||
<layout class="QFormLayout" name="formLayout">
|
<layout class="QFormLayout" name="formLayout">
|
||||||
<item row="0" column="0">
|
<item row="0" column="0">
|
||||||
<widget class="QLabel" name="label">
|
<widget class="QLabel" name="label">
|
||||||
@@ -70,29 +70,8 @@
|
|||||||
</item>
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
|
||||||
<layout class="QGridLayout" name="gridLayout">
|
|
||||||
<item row="0" column="0">
|
|
||||||
<widget class="QCheckBox" name="checkBoxSerial1">
|
|
||||||
<property name="text">
|
|
||||||
<string>Serial port 1</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="0" column="1">
|
|
||||||
<widget class="QCheckBox" name="checkBoxParallel1">
|
|
||||||
<property name="text">
|
|
||||||
<string>Parallel port 1</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="1" column="0">
|
<item row="1" column="0">
|
||||||
<widget class="QCheckBox" name="checkBoxSerial2">
|
<layout class="QGridLayout" name="gridLayout">
|
||||||
<property name="text">
|
|
||||||
<string>Serial port 2</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="1" column="1">
|
<item row="1" column="1">
|
||||||
<widget class="QCheckBox" name="checkBoxParallel2">
|
<widget class="QCheckBox" name="checkBoxParallel2">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
@@ -100,13 +79,6 @@
|
|||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="2" column="0">
|
|
||||||
<widget class="QCheckBox" name="checkBoxSerial3">
|
|
||||||
<property name="text">
|
|
||||||
<string>Serial port 3</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="2" column="1">
|
<item row="2" column="1">
|
||||||
<widget class="QCheckBox" name="checkBoxParallel3">
|
<widget class="QCheckBox" name="checkBoxParallel3">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
@@ -114,10 +86,17 @@
|
|||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="3" column="0">
|
<item row="2" column="0">
|
||||||
<widget class="QCheckBox" name="checkBoxSerial4">
|
<widget class="QCheckBox" name="checkBoxSerial3">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Serial port 4</string>
|
<string>Serial port 3</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="0" column="0">
|
||||||
|
<widget class="QCheckBox" name="checkBoxSerial1">
|
||||||
|
<property name="text">
|
||||||
|
<string>Serial port 1</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
@@ -128,9 +107,55 @@
|
|||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
<item row="1" column="0">
|
||||||
|
<widget class="QCheckBox" name="checkBoxSerial2">
|
||||||
|
<property name="text">
|
||||||
|
<string>Serial port 2</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="0" column="1">
|
||||||
|
<widget class="QCheckBox" name="checkBoxParallel1">
|
||||||
|
<property name="text">
|
||||||
|
<string>Parallel port 1</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="3" column="0">
|
||||||
|
<widget class="QCheckBox" name="checkBoxSerial4">
|
||||||
|
<property name="text">
|
||||||
|
<string>Serial port 4</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item row="3" column="0">
|
||||||
|
<layout class="QGridLayout" name="gridLayout_5">
|
||||||
|
<property name="sizeConstraint">
|
||||||
|
<enum>QLayout::SetDefaultConstraint</enum>
|
||||||
|
</property>
|
||||||
|
<item row="4" column="0">
|
||||||
|
<spacer name="horizontalSpacer">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Horizontal</enum>
|
||||||
|
</property>
|
||||||
|
<property name="sizeHint" stdset="0">
|
||||||
|
<size>
|
||||||
|
<width>40</width>
|
||||||
|
<height>20</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
</spacer>
|
||||||
|
</item>
|
||||||
|
<item row="2" column="0">
|
||||||
|
<widget class="QCheckBox" name="checkBoxSerialPassThru3">
|
||||||
|
<property name="text">
|
||||||
|
<string>Serial port passthrough 3</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="5" column="0" colspan="2">
|
||||||
<spacer name="verticalSpacer">
|
<spacer name="verticalSpacer">
|
||||||
<property name="orientation">
|
<property name="orientation">
|
||||||
<enum>Qt::Vertical</enum>
|
<enum>Qt::Vertical</enum>
|
||||||
@@ -143,6 +168,57 @@
|
|||||||
</property>
|
</property>
|
||||||
</spacer>
|
</spacer>
|
||||||
</item>
|
</item>
|
||||||
|
<item row="0" column="1">
|
||||||
|
<widget class="QPushButton" name="pushButtonSerialPassThru1">
|
||||||
|
<property name="text">
|
||||||
|
<string>Configure</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="0" column="0">
|
||||||
|
<widget class="QCheckBox" name="checkBoxSerialPassThru1">
|
||||||
|
<property name="text">
|
||||||
|
<string>Serial port passthrough 1</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="1" column="0">
|
||||||
|
<widget class="QCheckBox" name="checkBoxSerialPassThru2">
|
||||||
|
<property name="text">
|
||||||
|
<string>Serial port passthrough 2</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="3" column="0">
|
||||||
|
<widget class="QCheckBox" name="checkBoxSerialPassThru4">
|
||||||
|
<property name="text">
|
||||||
|
<string>Serial port passthrough 4</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="1" column="1">
|
||||||
|
<widget class="QPushButton" name="pushButtonSerialPassThru2">
|
||||||
|
<property name="text">
|
||||||
|
<string>Configure</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="2" column="1">
|
||||||
|
<widget class="QPushButton" name="pushButtonSerialPassThru3">
|
||||||
|
<property name="text">
|
||||||
|
<string>Configure</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="3" column="1">
|
||||||
|
<widget class="QPushButton" name="pushButtonSerialPassThru4">
|
||||||
|
<property name="text">
|
||||||
|
<string>Configure</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
<resources/>
|
<resources/>
|
||||||
|
|||||||
@@ -17,7 +17,7 @@
|
|||||||
|
|
||||||
#include "qt_winmanagerfilter.hpp"
|
#include "qt_winmanagerfilter.hpp"
|
||||||
|
|
||||||
#include <Windows.h>
|
#include <windows.h>
|
||||||
#include <86box/win.h>
|
#include <86box/win.h>
|
||||||
|
|
||||||
bool
|
bool
|
||||||
|
|||||||
@@ -35,7 +35,7 @@
|
|||||||
|
|
||||||
#include <QMenuBar>
|
#include <QMenuBar>
|
||||||
|
|
||||||
#include <Windows.h>
|
#include <windows.h>
|
||||||
|
|
||||||
#include <86box/keyboard.h>
|
#include <86box/keyboard.h>
|
||||||
#include <86box/mouse.h>
|
#include <86box/mouse.h>
|
||||||
|
|||||||
@@ -37,7 +37,7 @@
|
|||||||
#include <QAbstractNativeEventFilter>
|
#include <QAbstractNativeEventFilter>
|
||||||
#include <QByteArray>
|
#include <QByteArray>
|
||||||
|
|
||||||
#include <Windows.h>
|
#include <windows.h>
|
||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
|
|||||||
@@ -13,9 +13,11 @@
|
|||||||
#
|
#
|
||||||
# Copyright 2021 Cacodemon345.
|
# Copyright 2021 Cacodemon345.
|
||||||
# Copyright 2021 David Hrdlička.
|
# Copyright 2021 David Hrdlička.
|
||||||
|
# Copyright 2021 Andreas J. Reichel.
|
||||||
|
# Copyright 2021-2022 Jasmine Iwanek.
|
||||||
#
|
#
|
||||||
|
|
||||||
add_library(plat OBJECT unix.c)
|
add_library(plat OBJECT unix.c unix_serial_passthrough.c)
|
||||||
|
|
||||||
if (NOT CPPTHREADS)
|
if (NOT CPPTHREADS)
|
||||||
target_sources(plat PRIVATE unix_thread.c)
|
target_sources(plat PRIVATE unix_thread.c)
|
||||||
|
|||||||
314
src/unix/unix_serial_passthrough.c
Normal file
314
src/unix/unix_serial_passthrough.c
Normal file
@@ -0,0 +1,314 @@
|
|||||||
|
/*
|
||||||
|
* 86Box A hypervisor and IBM PC system emulator that specializes in
|
||||||
|
* running old operating systems and software designed for IBM
|
||||||
|
* PC systems and compatibles from 1981 through fairly recent
|
||||||
|
* system designs based on the PCI bus.
|
||||||
|
*
|
||||||
|
* This file is part of the 86Box distribution.
|
||||||
|
*
|
||||||
|
* Definitions for platform specific serial to host passthrough
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* Authors: Andreas J. Reichel <webmaster@6th-dimension.com>,
|
||||||
|
* Jasmine Iwanek <jasmine@iwanek.co.uk>
|
||||||
|
*
|
||||||
|
* Copyright 2021 Andreas J. Reichel.
|
||||||
|
* Copyright 2021-2022 Jasmine Iwanek.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __APPLE__
|
||||||
|
# define _XOPEN_SOURCE 500
|
||||||
|
# define _DEFAULT_SOURCE 1
|
||||||
|
# define _BSD_SOURCE 1
|
||||||
|
#endif
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <sys/select.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <sys/select.h>
|
||||||
|
|
||||||
|
#include <86box/86box.h>
|
||||||
|
#include <86box/log.h>
|
||||||
|
#include <86box/plat.h>
|
||||||
|
#include <86box/device.h>
|
||||||
|
#include <86box/serial_passthrough.h>
|
||||||
|
#include <86box/plat_serial_passthrough.h>
|
||||||
|
#include <termios.h>
|
||||||
|
#include <errno.h>
|
||||||
|
|
||||||
|
#define LOG_PREFIX "serial_passthrough: "
|
||||||
|
|
||||||
|
int
|
||||||
|
plat_serpt_read(void *p, uint8_t *data)
|
||||||
|
{
|
||||||
|
serial_passthrough_t *dev = (serial_passthrough_t *) p;
|
||||||
|
int res;
|
||||||
|
struct timeval tv;
|
||||||
|
fd_set rdfds;
|
||||||
|
|
||||||
|
switch (dev->mode) {
|
||||||
|
case SERPT_MODE_VCON:
|
||||||
|
case SERPT_MODE_HOSTSER:
|
||||||
|
FD_ZERO(&rdfds);
|
||||||
|
FD_SET(dev->master_fd, &rdfds);
|
||||||
|
tv.tv_sec = 0;
|
||||||
|
tv.tv_usec = 0;
|
||||||
|
|
||||||
|
res = select(dev->master_fd + 1, &rdfds, NULL, NULL, &tv);
|
||||||
|
if (res <= 0 || !FD_ISSET(dev->master_fd, &rdfds)) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (read(dev->master_fd, data, 1) > 0) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
plat_serpt_close(void *p)
|
||||||
|
{
|
||||||
|
serial_passthrough_t *dev = (serial_passthrough_t *) p;
|
||||||
|
|
||||||
|
if (dev->mode == SERPT_MODE_HOSTSER) {
|
||||||
|
tcsetattr(dev->master_fd, TCSANOW, (struct termios *) dev->backend_priv);
|
||||||
|
free(dev->backend_priv);
|
||||||
|
}
|
||||||
|
close(dev->master_fd);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
plat_serpt_write_vcon(serial_passthrough_t *dev, uint8_t data)
|
||||||
|
{
|
||||||
|
/* fd_set wrfds;
|
||||||
|
* int res;
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* We cannot use select here, this would block the hypervisor! */
|
||||||
|
/* FD_ZERO(&wrfds);
|
||||||
|
FD_SET(ctx->master_fd, &wrfds);
|
||||||
|
|
||||||
|
res = select(ctx->master_fd + 1, NULL, &wrfds, NULL, NULL);
|
||||||
|
|
||||||
|
if (res <= 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* just write it out */
|
||||||
|
if (dev->mode == SERPT_MODE_HOSTSER) {
|
||||||
|
int res = 0;
|
||||||
|
do {
|
||||||
|
res = write(dev->master_fd, &data, 1);
|
||||||
|
} while (res == 0 || (res == -1 && (errno == EAGAIN || res == EWOULDBLOCK)));
|
||||||
|
} else
|
||||||
|
write(dev->master_fd, &data, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
plat_serpt_set_params(void *p)
|
||||||
|
{
|
||||||
|
serial_passthrough_t *dev = (serial_passthrough_t *) p;
|
||||||
|
|
||||||
|
if (dev->mode == SERPT_MODE_HOSTSER) {
|
||||||
|
struct termios term_attr;
|
||||||
|
tcgetattr(dev->master_fd, &term_attr);
|
||||||
|
#define BAUDRATE_RANGE(baud_rate, min, max, val) \
|
||||||
|
if (baud_rate >= min && baud_rate < max) { \
|
||||||
|
cfsetispeed(&term_attr, val); \
|
||||||
|
cfsetospeed(&term_attr, val); \
|
||||||
|
}
|
||||||
|
|
||||||
|
BAUDRATE_RANGE(dev->baudrate, 50, 75, B50);
|
||||||
|
BAUDRATE_RANGE(dev->baudrate, 75, 110, B75);
|
||||||
|
BAUDRATE_RANGE(dev->baudrate, 110, 134, B110);
|
||||||
|
BAUDRATE_RANGE(dev->baudrate, 134, 150, B134);
|
||||||
|
BAUDRATE_RANGE(dev->baudrate, 150, 200, B150);
|
||||||
|
BAUDRATE_RANGE(dev->baudrate, 200, 300, B200);
|
||||||
|
BAUDRATE_RANGE(dev->baudrate, 300, 600, B300);
|
||||||
|
BAUDRATE_RANGE(dev->baudrate, 600, 1200, B600);
|
||||||
|
BAUDRATE_RANGE(dev->baudrate, 1200, 1800, B1200);
|
||||||
|
BAUDRATE_RANGE(dev->baudrate, 1800, 2400, B1800);
|
||||||
|
BAUDRATE_RANGE(dev->baudrate, 2400, 4800, B2400);
|
||||||
|
BAUDRATE_RANGE(dev->baudrate, 4800, 9600, B4800);
|
||||||
|
BAUDRATE_RANGE(dev->baudrate, 9600, 19200, B9600);
|
||||||
|
BAUDRATE_RANGE(dev->baudrate, 19200, 38400, B19200);
|
||||||
|
BAUDRATE_RANGE(dev->baudrate, 38400, 57600, B38400);
|
||||||
|
BAUDRATE_RANGE(dev->baudrate, 57600, 115200, B57600);
|
||||||
|
BAUDRATE_RANGE(dev->baudrate, 115200, 0xFFFFFFFF, B115200);
|
||||||
|
|
||||||
|
term_attr.c_cflag &= CSIZE;
|
||||||
|
switch (dev->data_bits) {
|
||||||
|
case 8:
|
||||||
|
default:
|
||||||
|
term_attr.c_cflag |= CS8;
|
||||||
|
break;
|
||||||
|
case 7:
|
||||||
|
term_attr.c_cflag |= CS7;
|
||||||
|
break;
|
||||||
|
case 6:
|
||||||
|
term_attr.c_cflag |= CS6;
|
||||||
|
break;
|
||||||
|
case 5:
|
||||||
|
term_attr.c_cflag |= CS5;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
term_attr.c_cflag &= CSTOPB;
|
||||||
|
if (dev->serial->lcr & 0x04)
|
||||||
|
term_attr.c_cflag |= CSTOPB;
|
||||||
|
#ifdef __APPLE__
|
||||||
|
term_attr.c_cflag &= PARENB | PARODD;
|
||||||
|
#else
|
||||||
|
term_attr.c_cflag &= PARENB | PARODD | CMSPAR;
|
||||||
|
#endif
|
||||||
|
if (dev->serial->lcr & 0x08) {
|
||||||
|
term_attr.c_cflag |= PARENB;
|
||||||
|
if (!(dev->serial->lcr & 0x10))
|
||||||
|
term_attr.c_cflag |= PARODD;
|
||||||
|
#ifndef __APPLE__
|
||||||
|
if ((dev->serial->lcr & 0x20))
|
||||||
|
term_attr.c_cflag |= CMSPAR;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
tcsetattr(dev->master_fd, TCSANOW, &term_attr);
|
||||||
|
#undef BAUDRATE_RANGE
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
plat_serpt_write(void *p, uint8_t data)
|
||||||
|
{
|
||||||
|
serial_passthrough_t *dev = (serial_passthrough_t *) p;
|
||||||
|
|
||||||
|
switch (dev->mode) {
|
||||||
|
case SERPT_MODE_VCON:
|
||||||
|
case SERPT_MODE_HOSTSER:
|
||||||
|
plat_serpt_write_vcon(dev, data);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
open_pseudo_terminal(serial_passthrough_t *dev)
|
||||||
|
{
|
||||||
|
int master_fd = open("/dev/ptmx", O_RDWR | O_NONBLOCK);
|
||||||
|
char *ptname;
|
||||||
|
struct termios term_attr_raw;
|
||||||
|
|
||||||
|
if (!master_fd) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* get name of slave device */
|
||||||
|
if (!(ptname = ptsname(master_fd))) {
|
||||||
|
pclog(LOG_PREFIX "could not get name of slave pseudo terminal");
|
||||||
|
close(master_fd);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
memset(dev->slave_pt, 0, sizeof(dev->slave_pt));
|
||||||
|
strncpy(dev->slave_pt, ptname, sizeof(dev->slave_pt) - 1);
|
||||||
|
|
||||||
|
fprintf(stderr, LOG_PREFIX "Slave side is %s\n", dev->slave_pt);
|
||||||
|
|
||||||
|
if (grantpt(master_fd)) {
|
||||||
|
pclog(LOG_PREFIX "error in grantpt()\n");
|
||||||
|
close(master_fd);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (unlockpt(master_fd)) {
|
||||||
|
pclog(LOG_PREFIX "error in unlockpt()\n");
|
||||||
|
close(master_fd);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
tcgetattr(master_fd, &term_attr_raw);
|
||||||
|
cfmakeraw(&term_attr_raw);
|
||||||
|
tcsetattr(master_fd, TCSANOW, &term_attr_raw);
|
||||||
|
|
||||||
|
dev->master_fd = master_fd;
|
||||||
|
|
||||||
|
return master_fd;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
open_host_serial_port(serial_passthrough_t *dev)
|
||||||
|
{
|
||||||
|
struct termios *term_attr = NULL;
|
||||||
|
struct termios term_attr_raw = {};
|
||||||
|
int fd = open(dev->host_serial_path, O_RDWR | O_NOCTTY | O_NONBLOCK);
|
||||||
|
if (fd == -1) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isatty(fd)) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
term_attr = calloc(1, sizeof(struct termios));
|
||||||
|
if (!term_attr) {
|
||||||
|
close(fd);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tcgetattr(fd, term_attr) == -1) {
|
||||||
|
free(term_attr);
|
||||||
|
close(fd);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
term_attr_raw = *term_attr;
|
||||||
|
/* "Raw" mode. */
|
||||||
|
cfmakeraw(&term_attr_raw);
|
||||||
|
term_attr_raw.c_cflag &= CSIZE;
|
||||||
|
switch (dev->data_bits) {
|
||||||
|
case 8:
|
||||||
|
default:
|
||||||
|
term_attr_raw.c_cflag |= CS8;
|
||||||
|
break;
|
||||||
|
case 7:
|
||||||
|
term_attr_raw.c_cflag |= CS7;
|
||||||
|
break;
|
||||||
|
case 6:
|
||||||
|
term_attr_raw.c_cflag |= CS6;
|
||||||
|
break;
|
||||||
|
case 5:
|
||||||
|
term_attr_raw.c_cflag |= CS5;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
tcsetattr(fd, TCSANOW, &term_attr_raw);
|
||||||
|
dev->backend_priv = term_attr;
|
||||||
|
dev->master_fd = fd;
|
||||||
|
pclog(LOG_PREFIX "Opened host TTY/serial port %s\n", dev->host_serial_path);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
plat_serpt_open_device(void *p)
|
||||||
|
{
|
||||||
|
serial_passthrough_t *dev = (serial_passthrough_t *) p;
|
||||||
|
|
||||||
|
switch (dev->mode) {
|
||||||
|
case SERPT_MODE_VCON:
|
||||||
|
if (!open_pseudo_terminal(dev)) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case SERPT_MODE_HOSTSER:
|
||||||
|
if (!open_host_serial_port(dev)) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
@@ -10,13 +10,14 @@
|
|||||||
#
|
#
|
||||||
# Authors: David Hrdlička, <hrdlickadavid@outlook.com>
|
# Authors: David Hrdlička, <hrdlickadavid@outlook.com>
|
||||||
#
|
#
|
||||||
# Copyright 2020-2021 David Hrdlička.
|
# Copyright 2020,2021 David Hrdlička.
|
||||||
|
# Copyright 2021-2022 Jasmine Iwanek.
|
||||||
#
|
#
|
||||||
|
|
||||||
enable_language(RC)
|
enable_language(RC)
|
||||||
|
|
||||||
add_library(plat OBJECT win.c win_dynld.c win_cdrom.c win_keyboard.c
|
add_library(plat OBJECT win.c win_dynld.c win_cdrom.c win_keyboard.c
|
||||||
win_mouse.c)
|
win_mouse.c win_serial_passthrough.c)
|
||||||
|
|
||||||
add_library(ui OBJECT win_ui.c win_icon.c win_stbar.c win_sdl.c win_dialog.c win_about.c
|
add_library(ui OBJECT win_ui.c win_icon.c win_stbar.c win_sdl.c win_dialog.c win_about.c
|
||||||
win_settings.c win_devconf.c win_snd_gain.c win_specify_dim.c win_new_floppy.c
|
win_settings.c win_devconf.c win_snd_gain.c win_specify_dim.c win_new_floppy.c
|
||||||
|
|||||||
@@ -596,7 +596,7 @@ DEVOBJ := bugger.o cartridge.o cassette.o hasp.o hwm.o hwm_lm75.o hwm_lm78.o hwm
|
|||||||
mouse.o \
|
mouse.o \
|
||||||
mouse_bus.o \
|
mouse_bus.o \
|
||||||
mouse_serial.o mouse_ps2.o \
|
mouse_serial.o mouse_ps2.o \
|
||||||
phoenix_486_jumper.o
|
phoenix_486_jumper.o serial_passthrough.o
|
||||||
|
|
||||||
SIOOBJ := sio_acc3221.o sio_ali5123.o \
|
SIOOBJ := sio_acc3221.o sio_ali5123.o \
|
||||||
sio_f82c710.o sio_82091aa.o sio_fdc37c6xx.o \
|
sio_f82c710.o sio_82091aa.o sio_fdc37c6xx.o \
|
||||||
@@ -749,7 +749,7 @@ VOODOOOBJ := vid_voodoo.o vid_voodoo_banshee.o \
|
|||||||
PLATOBJ := win.o \
|
PLATOBJ := win.o \
|
||||||
win_dynld.o \
|
win_dynld.o \
|
||||||
win_cdrom.o win_keyboard.o \
|
win_cdrom.o win_keyboard.o \
|
||||||
win_mouse.o
|
win_mouse.o win_serial_passthrough.o
|
||||||
|
|
||||||
UIOBJ := win_ui.o win_icon.o win_stbar.o discord.o \
|
UIOBJ := win_ui.o win_icon.o win_stbar.o discord.o \
|
||||||
win_sdl.o win_opengl.o win_opengl_glslp.o glad.o \
|
win_sdl.o win_opengl.o win_opengl_glslp.o glad.o \
|
||||||
|
|||||||
@@ -328,6 +328,10 @@ END
|
|||||||
#define STR_PARALLEL2 "Povolit port LPT2"
|
#define STR_PARALLEL2 "Povolit port LPT2"
|
||||||
#define STR_PARALLEL3 "Povolit port LPT3"
|
#define STR_PARALLEL3 "Povolit port LPT3"
|
||||||
#define STR_PARALLEL4 "Povolit port LPT4"
|
#define STR_PARALLEL4 "Povolit port LPT4"
|
||||||
|
#define STR_SERIAL_PASS1 "Serial port passthrough 1"
|
||||||
|
#define STR_SERIAL_PASS2 "Serial port passthrough 2"
|
||||||
|
#define STR_SERIAL_PASS3 "Serial port passthrough 3"
|
||||||
|
#define STR_SERIAL_PASS4 "Serial port passthrough 4"
|
||||||
|
|
||||||
#define STR_HDC "Řadič disku:"
|
#define STR_HDC "Řadič disku:"
|
||||||
#define STR_FDC "Disketový řadič:"
|
#define STR_FDC "Disketový řadič:"
|
||||||
|
|||||||
@@ -328,6 +328,10 @@ END
|
|||||||
#define STR_PARALLEL2 "Parallelport 2"
|
#define STR_PARALLEL2 "Parallelport 2"
|
||||||
#define STR_PARALLEL3 "Parallelport 3"
|
#define STR_PARALLEL3 "Parallelport 3"
|
||||||
#define STR_PARALLEL4 "Parallelport 4"
|
#define STR_PARALLEL4 "Parallelport 4"
|
||||||
|
#define STR_SERIAL_PASS1 "Serial port passthrough 1"
|
||||||
|
#define STR_SERIAL_PASS2 "Serial port passthrough 2"
|
||||||
|
#define STR_SERIAL_PASS3 "Serial port passthrough 3"
|
||||||
|
#define STR_SERIAL_PASS4 "Serial port passthrough 4"
|
||||||
|
|
||||||
#define STR_HDC "HDD-Controller:"
|
#define STR_HDC "HDD-Controller:"
|
||||||
#define STR_FDC "FD-Controller:"
|
#define STR_FDC "FD-Controller:"
|
||||||
|
|||||||
@@ -453,54 +453,78 @@ BEGIN
|
|||||||
CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
|
CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
|
||||||
|
|
||||||
LTEXT STR_LPT2, IDT_LPT2,
|
LTEXT STR_LPT2, IDT_LPT2,
|
||||||
CFG_HMARGIN, 28, CFG_PANE_LTEXT_PRI_WIDTH, CFG_PANE_LTEXT_HEIGHT
|
CFG_HMARGIN, 24, CFG_PANE_LTEXT_PRI_WIDTH, CFG_PANE_LTEXT_HEIGHT
|
||||||
COMBOBOX IDC_COMBO_LPT2,
|
COMBOBOX IDC_COMBO_LPT2,
|
||||||
CFG_COMBO_BOX_LEFT, 26, CFG_COMBO_NOBTN_WIDTH, CFG_COMBO_HEIGHT,
|
CFG_COMBO_BOX_LEFT, 22, CFG_COMBO_NOBTN_WIDTH, CFG_COMBO_HEIGHT,
|
||||||
CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
|
CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
|
||||||
|
|
||||||
LTEXT STR_LPT3, IDT_LPT3,
|
LTEXT STR_LPT3, IDT_LPT3,
|
||||||
CFG_HMARGIN, 47, CFG_PANE_LTEXT_PRI_WIDTH, CFG_PANE_LTEXT_HEIGHT
|
CFG_HMARGIN, 39, CFG_PANE_LTEXT_PRI_WIDTH, CFG_PANE_LTEXT_HEIGHT
|
||||||
COMBOBOX IDC_COMBO_LPT3,
|
COMBOBOX IDC_COMBO_LPT3,
|
||||||
CFG_COMBO_BOX_LEFT, 45, CFG_COMBO_NOBTN_WIDTH, CFG_COMBO_HEIGHT,
|
CFG_COMBO_BOX_LEFT, 37, CFG_COMBO_NOBTN_WIDTH, CFG_COMBO_HEIGHT,
|
||||||
CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
|
CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
|
||||||
|
|
||||||
LTEXT STR_LPT4, IDT_LPT4,
|
LTEXT STR_LPT4, IDT_LPT4,
|
||||||
CFG_HMARGIN, 66, CFG_PANE_LTEXT_PRI_WIDTH, CFG_PANE_LTEXT_HEIGHT
|
CFG_HMARGIN, 54, CFG_PANE_LTEXT_PRI_WIDTH, CFG_PANE_LTEXT_HEIGHT
|
||||||
COMBOBOX IDC_COMBO_LPT4,
|
COMBOBOX IDC_COMBO_LPT4,
|
||||||
CFG_COMBO_BOX_LEFT, 64, CFG_COMBO_NOBTN_WIDTH, CFG_COMBO_HEIGHT,
|
CFG_COMBO_BOX_LEFT, 52, CFG_COMBO_NOBTN_WIDTH, CFG_COMBO_HEIGHT,
|
||||||
CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
|
CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
|
||||||
|
|
||||||
CONTROL STR_SERIAL1, IDC_CHECK_SERIAL1,
|
CONTROL STR_SERIAL1, IDC_CHECK_SERIAL1,
|
||||||
"Button", BS_AUTOCHECKBOX | WS_TABSTOP,
|
"Button", BS_AUTOCHECKBOX | WS_TABSTOP,
|
||||||
CFG_HMARGIN, 83, CFG_CHECKBOX_PRI_WIDTH, CFG_CHECKBOX_HEIGHT
|
CFG_HMARGIN, 71, CFG_CHECKBOX_PRI_WIDTH, CFG_CHECKBOX_HEIGHT
|
||||||
|
|
||||||
CONTROL STR_SERIAL2, IDC_CHECK_SERIAL2,
|
CONTROL STR_SERIAL2, IDC_CHECK_SERIAL2,
|
||||||
"Button", BS_AUTOCHECKBOX | WS_TABSTOP,
|
"Button", BS_AUTOCHECKBOX | WS_TABSTOP,
|
||||||
CFG_HMARGIN, 102, CFG_CHECKBOX_PRI_WIDTH, CFG_CHECKBOX_HEIGHT
|
CFG_HMARGIN, 86, CFG_CHECKBOX_PRI_WIDTH, CFG_CHECKBOX_HEIGHT
|
||||||
|
|
||||||
CONTROL STR_SERIAL3, IDC_CHECK_SERIAL3,
|
CONTROL STR_SERIAL3, IDC_CHECK_SERIAL3,
|
||||||
"Button", BS_AUTOCHECKBOX | WS_TABSTOP,
|
"Button", BS_AUTOCHECKBOX | WS_TABSTOP,
|
||||||
CFG_HMARGIN, 121, CFG_CHECKBOX_PRI_WIDTH, CFG_CHECKBOX_HEIGHT
|
CFG_HMARGIN, 101, CFG_CHECKBOX_PRI_WIDTH, CFG_CHECKBOX_HEIGHT
|
||||||
|
|
||||||
CONTROL STR_SERIAL4, IDC_CHECK_SERIAL4,
|
CONTROL STR_SERIAL4, IDC_CHECK_SERIAL4,
|
||||||
"Button", BS_AUTOCHECKBOX | WS_TABSTOP,
|
"Button", BS_AUTOCHECKBOX | WS_TABSTOP,
|
||||||
CFG_HMARGIN, 140, CFG_CHECKBOX_PRI_WIDTH, CFG_CHECKBOX_HEIGHT
|
CFG_HMARGIN, 116, CFG_CHECKBOX_PRI_WIDTH, CFG_CHECKBOX_HEIGHT
|
||||||
|
|
||||||
CONTROL STR_PARALLEL1, IDC_CHECK_PARALLEL1,
|
CONTROL STR_PARALLEL1, IDC_CHECK_PARALLEL1,
|
||||||
"Button", BS_AUTOCHECKBOX | WS_TABSTOP,
|
"Button", BS_AUTOCHECKBOX | WS_TABSTOP,
|
||||||
167, 83, CFG_CHECKBOX_PRI_WIDTH, CFG_CHECKBOX_HEIGHT
|
167, 71, CFG_CHECKBOX_PRI_WIDTH, CFG_CHECKBOX_HEIGHT
|
||||||
|
|
||||||
CONTROL STR_PARALLEL2, IDC_CHECK_PARALLEL2,
|
CONTROL STR_PARALLEL2, IDC_CHECK_PARALLEL2,
|
||||||
"Button", BS_AUTOCHECKBOX | WS_TABSTOP,
|
"Button", BS_AUTOCHECKBOX | WS_TABSTOP,
|
||||||
167, 102, CFG_CHECKBOX_PRI_WIDTH, CFG_CHECKBOX_HEIGHT
|
167, 86, CFG_CHECKBOX_PRI_WIDTH, CFG_CHECKBOX_HEIGHT
|
||||||
|
|
||||||
CONTROL STR_PARALLEL3, IDC_CHECK_PARALLEL3,
|
CONTROL STR_PARALLEL3, IDC_CHECK_PARALLEL3,
|
||||||
"Button", BS_AUTOCHECKBOX | WS_TABSTOP,
|
"Button", BS_AUTOCHECKBOX | WS_TABSTOP,
|
||||||
167, 121, CFG_CHECKBOX_PRI_WIDTH, CFG_CHECKBOX_HEIGHT
|
167, 101, CFG_CHECKBOX_PRI_WIDTH, CFG_CHECKBOX_HEIGHT
|
||||||
|
|
||||||
CONTROL STR_PARALLEL4, IDC_CHECK_PARALLEL4,
|
CONTROL STR_PARALLEL4, IDC_CHECK_PARALLEL4,
|
||||||
"Button", BS_AUTOCHECKBOX | WS_TABSTOP,
|
"Button", BS_AUTOCHECKBOX | WS_TABSTOP,
|
||||||
167, 140, CFG_CHECKBOX_PRI_WIDTH, CFG_CHECKBOX_HEIGHT
|
167, 116, CFG_CHECKBOX_PRI_WIDTH, CFG_CHECKBOX_HEIGHT
|
||||||
|
|
||||||
|
CONTROL STR_SERIAL_PASS1, IDC_CHECK_SERIAL_PASS1,
|
||||||
|
"Button", BS_AUTOCHECKBOX | WS_TABSTOP,
|
||||||
|
CFG_HMARGIN, 134, CFG_CHECKBOX_PRI_WIDTH, CFG_CHECKBOX_HEIGHT
|
||||||
|
PUSHBUTTON STR_CONFIGURE, IDC_CONFIGURE_SERIAL_PASS1,
|
||||||
|
CFG_COMBO_BTN_LEFT, 131, CFG_BTN_WIDTH, CFG_BTN_HEIGHT
|
||||||
|
|
||||||
|
CONTROL STR_SERIAL_PASS2, IDC_CHECK_SERIAL_PASS2,
|
||||||
|
"Button", BS_AUTOCHECKBOX | WS_TABSTOP,
|
||||||
|
CFG_HMARGIN, 150, CFG_CHECKBOX_PRI_WIDTH, CFG_CHECKBOX_HEIGHT
|
||||||
|
PUSHBUTTON STR_CONFIGURE, IDC_CONFIGURE_SERIAL_PASS2,
|
||||||
|
CFG_COMBO_BTN_LEFT, 147, CFG_BTN_WIDTH, CFG_BTN_HEIGHT
|
||||||
|
|
||||||
|
CONTROL STR_SERIAL_PASS3, IDC_CHECK_SERIAL_PASS3,
|
||||||
|
"Button", BS_AUTOCHECKBOX | WS_TABSTOP,
|
||||||
|
CFG_HMARGIN, 165, CFG_CHECKBOX_PRI_WIDTH, CFG_CHECKBOX_HEIGHT
|
||||||
|
PUSHBUTTON STR_CONFIGURE, IDC_CONFIGURE_SERIAL_PASS3,
|
||||||
|
CFG_COMBO_BTN_LEFT, 162, CFG_BTN_WIDTH, CFG_BTN_HEIGHT
|
||||||
|
|
||||||
|
CONTROL STR_SERIAL_PASS4, IDC_CHECK_SERIAL_PASS4,
|
||||||
|
"Button", BS_AUTOCHECKBOX | WS_TABSTOP,
|
||||||
|
CFG_HMARGIN, 180, CFG_CHECKBOX_PRI_WIDTH, CFG_CHECKBOX_HEIGHT
|
||||||
|
PUSHBUTTON STR_CONFIGURE, IDC_CONFIGURE_SERIAL_PASS4,
|
||||||
|
CFG_COMBO_BTN_LEFT, 177, CFG_BTN_WIDTH, CFG_BTN_HEIGHT
|
||||||
END
|
END
|
||||||
|
|
||||||
DLG_CFG_STORAGE DIALOG DISCARDABLE CFG_PANE_LEFT, CFG_PANE_TOP, CFG_PANE_WIDTH, CFG_PANE_HEIGHT
|
DLG_CFG_STORAGE DIALOG DISCARDABLE CFG_PANE_LEFT, CFG_PANE_TOP, CFG_PANE_WIDTH, CFG_PANE_HEIGHT
|
||||||
@@ -996,6 +1020,10 @@ END
|
|||||||
#undef STR_PARALLEL2
|
#undef STR_PARALLEL2
|
||||||
#undef STR_PARALLEL3
|
#undef STR_PARALLEL3
|
||||||
#undef STR_PARALLEL4
|
#undef STR_PARALLEL4
|
||||||
|
#undef STR_SERIAL_PASS1
|
||||||
|
#undef STR_SERIAL_PASS2
|
||||||
|
#undef STR_SERIAL_PASS3
|
||||||
|
#undef STR_SERIAL_PASS4
|
||||||
|
|
||||||
#undef STR_HDC
|
#undef STR_HDC
|
||||||
#undef STR_FDC
|
#undef STR_FDC
|
||||||
|
|||||||
@@ -328,6 +328,10 @@ END
|
|||||||
#define STR_PARALLEL2 "Parallel port 2"
|
#define STR_PARALLEL2 "Parallel port 2"
|
||||||
#define STR_PARALLEL3 "Parallel port 3"
|
#define STR_PARALLEL3 "Parallel port 3"
|
||||||
#define STR_PARALLEL4 "Parallel port 4"
|
#define STR_PARALLEL4 "Parallel port 4"
|
||||||
|
#define STR_SERIAL_PASS1 "Serial port passthrough 1"
|
||||||
|
#define STR_SERIAL_PASS2 "Serial port passthrough 2"
|
||||||
|
#define STR_SERIAL_PASS3 "Serial port passthrough 3"
|
||||||
|
#define STR_SERIAL_PASS4 "Serial port passthrough 4"
|
||||||
|
|
||||||
#define STR_HDC "HD Controller:"
|
#define STR_HDC "HD Controller:"
|
||||||
#define STR_FDC "FD Controller:"
|
#define STR_FDC "FD Controller:"
|
||||||
|
|||||||
@@ -328,6 +328,10 @@ END
|
|||||||
#define STR_PARALLEL2 "Parallel port 2"
|
#define STR_PARALLEL2 "Parallel port 2"
|
||||||
#define STR_PARALLEL3 "Parallel port 3"
|
#define STR_PARALLEL3 "Parallel port 3"
|
||||||
#define STR_PARALLEL4 "Parallel port 4"
|
#define STR_PARALLEL4 "Parallel port 4"
|
||||||
|
#define STR_SERIAL_PASS1 "Serial port passthrough 1"
|
||||||
|
#define STR_SERIAL_PASS2 "Serial port passthrough 2"
|
||||||
|
#define STR_SERIAL_PASS3 "Serial port passthrough 3"
|
||||||
|
#define STR_SERIAL_PASS4 "Serial port passthrough 4"
|
||||||
|
|
||||||
#define STR_HDC "HD Controller:"
|
#define STR_HDC "HD Controller:"
|
||||||
#define STR_FDC "FD Controller:"
|
#define STR_FDC "FD Controller:"
|
||||||
|
|||||||
@@ -328,6 +328,10 @@ END
|
|||||||
#define STR_PARALLEL2 "Puerto paralelo 2"
|
#define STR_PARALLEL2 "Puerto paralelo 2"
|
||||||
#define STR_PARALLEL3 "Puerto paralelo 3"
|
#define STR_PARALLEL3 "Puerto paralelo 3"
|
||||||
#define STR_PARALLEL4 "Puerto paralelo 4"
|
#define STR_PARALLEL4 "Puerto paralelo 4"
|
||||||
|
#define STR_SERIAL_PASS1 "Serial port passthrough 1"
|
||||||
|
#define STR_SERIAL_PASS2 "Serial port passthrough 2"
|
||||||
|
#define STR_SERIAL_PASS3 "Serial port passthrough 3"
|
||||||
|
#define STR_SERIAL_PASS4 "Serial port passthrough 4"
|
||||||
|
|
||||||
#define STR_HDC "Controladora HD:"
|
#define STR_HDC "Controladora HD:"
|
||||||
#define STR_FDC "Controladora FD:"
|
#define STR_FDC "Controladora FD:"
|
||||||
|
|||||||
@@ -328,6 +328,10 @@ END
|
|||||||
#define STR_PARALLEL2 "Rinnakkaisportti 2"
|
#define STR_PARALLEL2 "Rinnakkaisportti 2"
|
||||||
#define STR_PARALLEL3 "Rinnakkaisportti 3"
|
#define STR_PARALLEL3 "Rinnakkaisportti 3"
|
||||||
#define STR_PARALLEL4 "Rinnakkaisportti 4"
|
#define STR_PARALLEL4 "Rinnakkaisportti 4"
|
||||||
|
#define STR_SERIAL_PASS1 "Serial port passthrough 1"
|
||||||
|
#define STR_SERIAL_PASS2 "Serial port passthrough 2"
|
||||||
|
#define STR_SERIAL_PASS3 "Serial port passthrough 3"
|
||||||
|
#define STR_SERIAL_PASS4 "Serial port passthrough 4"
|
||||||
|
|
||||||
#define STR_HDC "Kiintolevyohjain:"
|
#define STR_HDC "Kiintolevyohjain:"
|
||||||
#define STR_FDC "Levykeohjain:"
|
#define STR_FDC "Levykeohjain:"
|
||||||
|
|||||||
@@ -328,6 +328,10 @@ END
|
|||||||
#define STR_PARALLEL2 "Port parallèle 2"
|
#define STR_PARALLEL2 "Port parallèle 2"
|
||||||
#define STR_PARALLEL3 "Port parallèle 3"
|
#define STR_PARALLEL3 "Port parallèle 3"
|
||||||
#define STR_PARALLEL4 "Port parallèle 4"
|
#define STR_PARALLEL4 "Port parallèle 4"
|
||||||
|
#define STR_SERIAL_PASS1 "Serial port passthrough 1"
|
||||||
|
#define STR_SERIAL_PASS2 "Serial port passthrough 2"
|
||||||
|
#define STR_SERIAL_PASS3 "Serial port passthrough 3"
|
||||||
|
#define STR_SERIAL_PASS4 "Serial port passthrough 4"
|
||||||
|
|
||||||
#define STR_HDC "Contrôleur HD:"
|
#define STR_HDC "Contrôleur HD:"
|
||||||
#define STR_FDC "Contrôleur FD:"
|
#define STR_FDC "Contrôleur FD:"
|
||||||
|
|||||||
@@ -328,6 +328,10 @@ END
|
|||||||
#define STR_PARALLEL2 "Paralelna vrata 2"
|
#define STR_PARALLEL2 "Paralelna vrata 2"
|
||||||
#define STR_PARALLEL3 "Paralelna vrata 3"
|
#define STR_PARALLEL3 "Paralelna vrata 3"
|
||||||
#define STR_PARALLEL4 "Paralelna vrata 4"
|
#define STR_PARALLEL4 "Paralelna vrata 4"
|
||||||
|
#define STR_SERIAL_PASS1 "Serial port passthrough 1"
|
||||||
|
#define STR_SERIAL_PASS2 "Serial port passthrough 2"
|
||||||
|
#define STR_SERIAL_PASS3 "Serial port passthrough 3"
|
||||||
|
#define STR_SERIAL_PASS4 "Serial port passthrough 4"
|
||||||
|
|
||||||
#define STR_HDC "Kontroler tvrdog diska:"
|
#define STR_HDC "Kontroler tvrdog diska:"
|
||||||
#define STR_FDC "Kontroler diskete:"
|
#define STR_FDC "Kontroler diskete:"
|
||||||
|
|||||||
@@ -333,6 +333,10 @@ END
|
|||||||
#define STR_PARALLEL2 "Párhuzamos port 2"
|
#define STR_PARALLEL2 "Párhuzamos port 2"
|
||||||
#define STR_PARALLEL3 "Párhuzamos port 3"
|
#define STR_PARALLEL3 "Párhuzamos port 3"
|
||||||
#define STR_PARALLEL4 "Párhuzamos port 4"
|
#define STR_PARALLEL4 "Párhuzamos port 4"
|
||||||
|
#define STR_SERIAL_PASS1 "Serial port passthrough 1"
|
||||||
|
#define STR_SERIAL_PASS2 "Serial port passthrough 2"
|
||||||
|
#define STR_SERIAL_PASS3 "Serial port passthrough 3"
|
||||||
|
#define STR_SERIAL_PASS4 "Serial port passthrough 4"
|
||||||
|
|
||||||
#define STR_HDC "Merevl.-vezérlő:"
|
#define STR_HDC "Merevl.-vezérlő:"
|
||||||
#define STR_FDC "Floppy-vezérlő:"
|
#define STR_FDC "Floppy-vezérlő:"
|
||||||
|
|||||||
@@ -329,6 +329,10 @@ END
|
|||||||
#define STR_PARALLEL2 "Porta parallela 2"
|
#define STR_PARALLEL2 "Porta parallela 2"
|
||||||
#define STR_PARALLEL3 "Porta parallela 3"
|
#define STR_PARALLEL3 "Porta parallela 3"
|
||||||
#define STR_PARALLEL4 "Porta parallela 4"
|
#define STR_PARALLEL4 "Porta parallela 4"
|
||||||
|
#define STR_SERIAL_PASS1 "Serial port passthrough 1"
|
||||||
|
#define STR_SERIAL_PASS2 "Serial port passthrough 2"
|
||||||
|
#define STR_SERIAL_PASS3 "Serial port passthrough 3"
|
||||||
|
#define STR_SERIAL_PASS4 "Serial port passthrough 4"
|
||||||
|
|
||||||
#define STR_HDC "Controller HD:"
|
#define STR_HDC "Controller HD:"
|
||||||
#define STR_FDC "Controller FD:"
|
#define STR_FDC "Controller FD:"
|
||||||
|
|||||||
@@ -328,6 +328,10 @@ END
|
|||||||
#define STR_PARALLEL2 "パラレルポート2"
|
#define STR_PARALLEL2 "パラレルポート2"
|
||||||
#define STR_PARALLEL3 "パラレルポート3"
|
#define STR_PARALLEL3 "パラレルポート3"
|
||||||
#define STR_PARALLEL4 "パラレルポート4"
|
#define STR_PARALLEL4 "パラレルポート4"
|
||||||
|
#define STR_SERIAL_PASS1 "Serial port passthrough 1"
|
||||||
|
#define STR_SERIAL_PASS2 "Serial port passthrough 2"
|
||||||
|
#define STR_SERIAL_PASS3 "Serial port passthrough 3"
|
||||||
|
#define STR_SERIAL_PASS4 "Serial port passthrough 4"
|
||||||
|
|
||||||
#define STR_HDC "HDコントローラー:"
|
#define STR_HDC "HDコントローラー:"
|
||||||
#define STR_FDC "FDコントローラー:"
|
#define STR_FDC "FDコントローラー:"
|
||||||
|
|||||||
@@ -328,6 +328,10 @@ END
|
|||||||
#define STR_PARALLEL2 "병렬 포트 2"
|
#define STR_PARALLEL2 "병렬 포트 2"
|
||||||
#define STR_PARALLEL3 "병렬 포트 3"
|
#define STR_PARALLEL3 "병렬 포트 3"
|
||||||
#define STR_PARALLEL4 "병렬 포트 4"
|
#define STR_PARALLEL4 "병렬 포트 4"
|
||||||
|
#define STR_SERIAL_PASS1 "Serial port passthrough 1"
|
||||||
|
#define STR_SERIAL_PASS2 "Serial port passthrough 2"
|
||||||
|
#define STR_SERIAL_PASS3 "Serial port passthrough 3"
|
||||||
|
#define STR_SERIAL_PASS4 "Serial port passthrough 4"
|
||||||
|
|
||||||
#define STR_HDC "HD 컨트롤러:"
|
#define STR_HDC "HD 컨트롤러:"
|
||||||
#define STR_FDC "FD 컨트롤러:"
|
#define STR_FDC "FD 컨트롤러:"
|
||||||
|
|||||||
@@ -328,6 +328,10 @@ END
|
|||||||
#define STR_PARALLEL2 "Port równoległy 2"
|
#define STR_PARALLEL2 "Port równoległy 2"
|
||||||
#define STR_PARALLEL3 "Port równoległy 3"
|
#define STR_PARALLEL3 "Port równoległy 3"
|
||||||
#define STR_PARALLEL4 "Port równoległy 4"
|
#define STR_PARALLEL4 "Port równoległy 4"
|
||||||
|
#define STR_SERIAL_PASS1 "Serial port passthrough 1"
|
||||||
|
#define STR_SERIAL_PASS2 "Serial port passthrough 2"
|
||||||
|
#define STR_SERIAL_PASS3 "Serial port passthrough 3"
|
||||||
|
#define STR_SERIAL_PASS4 "Serial port passthrough 4"
|
||||||
|
|
||||||
#define STR_HDC "Kontroler dysku twardego:"
|
#define STR_HDC "Kontroler dysku twardego:"
|
||||||
#define STR_FDC "Kontroler dyskietek:"
|
#define STR_FDC "Kontroler dyskietek:"
|
||||||
|
|||||||
@@ -331,6 +331,10 @@ END
|
|||||||
#define STR_PARALLEL2 "Porta paralela 2"
|
#define STR_PARALLEL2 "Porta paralela 2"
|
||||||
#define STR_PARALLEL3 "Porta paralela 3"
|
#define STR_PARALLEL3 "Porta paralela 3"
|
||||||
#define STR_PARALLEL4 "Porta paralela 4"
|
#define STR_PARALLEL4 "Porta paralela 4"
|
||||||
|
#define STR_SERIAL_PASS1 "Serial port passthrough 1"
|
||||||
|
#define STR_SERIAL_PASS2 "Serial port passthrough 2"
|
||||||
|
#define STR_SERIAL_PASS3 "Serial port passthrough 3"
|
||||||
|
#define STR_SERIAL_PASS4 "Serial port passthrough 4"
|
||||||
|
|
||||||
#define STR_HDC "Controlador HD:"
|
#define STR_HDC "Controlador HD:"
|
||||||
#define STR_FDC "Controlador FD:"
|
#define STR_FDC "Controlador FD:"
|
||||||
|
|||||||
@@ -328,6 +328,10 @@ END
|
|||||||
#define STR_PARALLEL2 "Porta paralela 2"
|
#define STR_PARALLEL2 "Porta paralela 2"
|
||||||
#define STR_PARALLEL3 "Porta paralela 3"
|
#define STR_PARALLEL3 "Porta paralela 3"
|
||||||
#define STR_PARALLEL4 "Porta paralela 4"
|
#define STR_PARALLEL4 "Porta paralela 4"
|
||||||
|
#define STR_SERIAL_PASS1 "Serial port passthrough 1"
|
||||||
|
#define STR_SERIAL_PASS2 "Serial port passthrough 2"
|
||||||
|
#define STR_SERIAL_PASS3 "Serial port passthrough 3"
|
||||||
|
#define STR_SERIAL_PASS4 "Serial port passthrough 4"
|
||||||
|
|
||||||
#define STR_HDC "Controlador HD:"
|
#define STR_HDC "Controlador HD:"
|
||||||
#define STR_FDC "Controlador FD:"
|
#define STR_FDC "Controlador FD:"
|
||||||
|
|||||||
@@ -328,6 +328,10 @@ END
|
|||||||
#define STR_PARALLEL2 "Параллельный порт LPT2"
|
#define STR_PARALLEL2 "Параллельный порт LPT2"
|
||||||
#define STR_PARALLEL3 "Параллельный порт LPT3"
|
#define STR_PARALLEL3 "Параллельный порт LPT3"
|
||||||
#define STR_PARALLEL4 "Параллельный порт LPT4"
|
#define STR_PARALLEL4 "Параллельный порт LPT4"
|
||||||
|
#define STR_SERIAL_PASS1 "Serial port passthrough 1"
|
||||||
|
#define STR_SERIAL_PASS2 "Serial port passthrough 2"
|
||||||
|
#define STR_SERIAL_PASS3 "Serial port passthrough 3"
|
||||||
|
#define STR_SERIAL_PASS4 "Serial port passthrough 4"
|
||||||
|
|
||||||
#define STR_HDC "Контроллер HD:"
|
#define STR_HDC "Контроллер HD:"
|
||||||
#define STR_FDC "Контроллер FD:"
|
#define STR_FDC "Контроллер FD:"
|
||||||
|
|||||||
@@ -328,6 +328,10 @@ END
|
|||||||
#define STR_PARALLEL2 "Paralelna vrata 2"
|
#define STR_PARALLEL2 "Paralelna vrata 2"
|
||||||
#define STR_PARALLEL3 "Paralelna vrata 3"
|
#define STR_PARALLEL3 "Paralelna vrata 3"
|
||||||
#define STR_PARALLEL4 "Paralelna vrata 4"
|
#define STR_PARALLEL4 "Paralelna vrata 4"
|
||||||
|
#define STR_SERIAL_PASS1 "Serial port passthrough 1"
|
||||||
|
#define STR_SERIAL_PASS2 "Serial port passthrough 2"
|
||||||
|
#define STR_SERIAL_PASS3 "Serial port passthrough 3"
|
||||||
|
#define STR_SERIAL_PASS4 "Serial port passthrough 4"
|
||||||
|
|
||||||
#define STR_HDC "Krmilnik trdega diska:"
|
#define STR_HDC "Krmilnik trdega diska:"
|
||||||
#define STR_FDC "Krmilnik disketnika:"
|
#define STR_FDC "Krmilnik disketnika:"
|
||||||
|
|||||||
@@ -328,6 +328,10 @@ END
|
|||||||
#define STR_PARALLEL2 "Paralel port 2"
|
#define STR_PARALLEL2 "Paralel port 2"
|
||||||
#define STR_PARALLEL3 "Paralel port 3"
|
#define STR_PARALLEL3 "Paralel port 3"
|
||||||
#define STR_PARALLEL4 "Paralel port 4"
|
#define STR_PARALLEL4 "Paralel port 4"
|
||||||
|
#define STR_SERIAL_PASS1 "Serial port passthrough 1"
|
||||||
|
#define STR_SERIAL_PASS2 "Serial port passthrough 2"
|
||||||
|
#define STR_SERIAL_PASS3 "Serial port passthrough 3"
|
||||||
|
#define STR_SERIAL_PASS4 "Serial port passthrough 4"
|
||||||
|
|
||||||
#define STR_HDC "HD Kontrolcüsü:"
|
#define STR_HDC "HD Kontrolcüsü:"
|
||||||
#define STR_FDC "FD Kontrolcüsü:"
|
#define STR_FDC "FD Kontrolcüsü:"
|
||||||
|
|||||||
@@ -328,6 +328,10 @@ END
|
|||||||
#define STR_PARALLEL2 "Паралельний порт LPT2"
|
#define STR_PARALLEL2 "Паралельний порт LPT2"
|
||||||
#define STR_PARALLEL3 "Паралельний порт LPT3"
|
#define STR_PARALLEL3 "Паралельний порт LPT3"
|
||||||
#define STR_PARALLEL4 "Паралельний порт LPT4"
|
#define STR_PARALLEL4 "Паралельний порт LPT4"
|
||||||
|
#define STR_SERIAL_PASS1 "Serial port passthrough 1"
|
||||||
|
#define STR_SERIAL_PASS2 "Serial port passthrough 2"
|
||||||
|
#define STR_SERIAL_PASS3 "Serial port passthrough 3"
|
||||||
|
#define STR_SERIAL_PASS4 "Serial port passthrough 4"
|
||||||
|
|
||||||
#define STR_HDC "Контролер HD:"
|
#define STR_HDC "Контролер HD:"
|
||||||
#define STR_FDC "Контролер FD:"
|
#define STR_FDC "Контролер FD:"
|
||||||
|
|||||||
@@ -328,6 +328,10 @@ END
|
|||||||
#define STR_PARALLEL2 "并口 2"
|
#define STR_PARALLEL2 "并口 2"
|
||||||
#define STR_PARALLEL3 "并口 3"
|
#define STR_PARALLEL3 "并口 3"
|
||||||
#define STR_PARALLEL4 "并口 4"
|
#define STR_PARALLEL4 "并口 4"
|
||||||
|
#define STR_SERIAL_PASS1 "Serial port passthrough 1"
|
||||||
|
#define STR_SERIAL_PASS2 "Serial port passthrough 2"
|
||||||
|
#define STR_SERIAL_PASS3 "Serial port passthrough 3"
|
||||||
|
#define STR_SERIAL_PASS4 "Serial port passthrough 4"
|
||||||
|
|
||||||
#define STR_HDC "硬盘控制器:"
|
#define STR_HDC "硬盘控制器:"
|
||||||
#define STR_FDC "软盘控制器:"
|
#define STR_FDC "软盘控制器:"
|
||||||
|
|||||||
@@ -328,6 +328,10 @@ END
|
|||||||
#define STR_PARALLEL2 "並列埠 2"
|
#define STR_PARALLEL2 "並列埠 2"
|
||||||
#define STR_PARALLEL3 "並列埠 3"
|
#define STR_PARALLEL3 "並列埠 3"
|
||||||
#define STR_PARALLEL4 "並列埠 4"
|
#define STR_PARALLEL4 "並列埠 4"
|
||||||
|
#define STR_SERIAL_PASS1 "Serial port passthrough 1"
|
||||||
|
#define STR_SERIAL_PASS2 "Serial port passthrough 2"
|
||||||
|
#define STR_SERIAL_PASS3 "Serial port passthrough 3"
|
||||||
|
#define STR_SERIAL_PASS4 "Serial port passthrough 4"
|
||||||
|
|
||||||
#define STR_HDC "硬碟控制器:"
|
#define STR_HDC "硬碟控制器:"
|
||||||
#define STR_FDC "軟碟控制器:"
|
#define STR_FDC "軟碟控制器:"
|
||||||
|
|||||||
@@ -36,7 +36,7 @@
|
|||||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
*/
|
*/
|
||||||
#define UNICODE
|
#define UNICODE
|
||||||
#include <Windows.h>
|
#include <windows.h>
|
||||||
#include <process.h>
|
#include <process.h>
|
||||||
#include <SDL2/SDL.h>
|
#include <SDL2/SDL.h>
|
||||||
#include <SDL2/SDL_syswm.h>
|
#include <SDL2/SDL_syswm.h>
|
||||||
|
|||||||
223
src/win/win_serial_passthrough.c
Normal file
223
src/win/win_serial_passthrough.c
Normal file
@@ -0,0 +1,223 @@
|
|||||||
|
/*
|
||||||
|
* 86Box A hypervisor and IBM PC system emulator that specializes in
|
||||||
|
* running old operating systems and software designed for IBM
|
||||||
|
* PC systems and compatibles from 1981 through fairly recent
|
||||||
|
* system designs based on the PCI bus.
|
||||||
|
*
|
||||||
|
* This file is part of the 86Box distribution.
|
||||||
|
*
|
||||||
|
* Definitions for platform specific serial to host passthrough
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* Authors: Andreas J. Reichel <webmaster@6th-dimension.com>,
|
||||||
|
* Jasmine Iwanek <jasmine@iwanek.co.uk>
|
||||||
|
*
|
||||||
|
* Copyright 2021 Andreas J. Reichel
|
||||||
|
* Copyright 2021-2022 Jasmine Iwanek
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define _XOPEN_SOURCE 500
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#include <86box/86box.h>
|
||||||
|
#include <86box/log.h>
|
||||||
|
#include <86box/timer.h>
|
||||||
|
#include <86box/plat.h>
|
||||||
|
#include <86box/device.h>
|
||||||
|
#include <86box/serial_passthrough.h>
|
||||||
|
#include <86box/plat_serial_passthrough.h>
|
||||||
|
|
||||||
|
#include <windows.h>
|
||||||
|
|
||||||
|
#define LOG_PREFIX "serial_passthrough: "
|
||||||
|
|
||||||
|
void
|
||||||
|
plat_serpt_close(void *p)
|
||||||
|
{
|
||||||
|
serial_passthrough_t *dev = (serial_passthrough_t *) p;
|
||||||
|
|
||||||
|
// fclose(dev->master_fd);
|
||||||
|
FlushFileBuffers((HANDLE) dev->master_fd);
|
||||||
|
if (dev->mode == SERPT_MODE_VCON)
|
||||||
|
DisconnectNamedPipe((HANDLE) dev->master_fd);
|
||||||
|
if (dev->mode == SERPT_MODE_HOSTSER) {
|
||||||
|
SetCommState((HANDLE)dev->master_fd, (DCB*)dev->backend_priv);
|
||||||
|
free(dev->backend_priv);
|
||||||
|
}
|
||||||
|
CloseHandle((HANDLE) dev->master_fd);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
plat_serpt_write_vcon(serial_passthrough_t *dev, uint8_t data)
|
||||||
|
{
|
||||||
|
/* fd_set wrfds;
|
||||||
|
* int res;
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* We cannot use select here, this would block the hypervisor! */
|
||||||
|
/* FD_ZERO(&wrfds);
|
||||||
|
FD_SET(ctx->master_fd, &wrfds);
|
||||||
|
|
||||||
|
res = select(ctx->master_fd + 1, NULL, &wrfds, NULL, NULL);
|
||||||
|
|
||||||
|
if (res <= 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* just write it out */
|
||||||
|
// fwrite(dev->master_fd, &data, 1);
|
||||||
|
DWORD bytesWritten = 0;
|
||||||
|
WriteFile((HANDLE) dev->master_fd, &data, 1, &bytesWritten, NULL);
|
||||||
|
if (bytesWritten == 0) {
|
||||||
|
fatal("serial_passthrough: WriteFile pipe write-buffer full!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
plat_serpt_set_params(void *p)
|
||||||
|
{
|
||||||
|
serial_passthrough_t *dev = (serial_passthrough_t *)p;
|
||||||
|
|
||||||
|
if (dev->mode == SERPT_MODE_HOSTSER) {
|
||||||
|
DCB serialattr = {};
|
||||||
|
GetCommState((HANDLE)dev->master_fd, &serialattr);
|
||||||
|
#define BAUDRATE_RANGE(baud_rate, min, max) if (baud_rate >= min && baud_rate < max) { serialattr.BaudRate = min; }
|
||||||
|
|
||||||
|
BAUDRATE_RANGE(dev->baudrate, 110, 300);
|
||||||
|
BAUDRATE_RANGE(dev->baudrate, 300, 600);
|
||||||
|
BAUDRATE_RANGE(dev->baudrate, 600, 1200);
|
||||||
|
BAUDRATE_RANGE(dev->baudrate, 1200, 2400);
|
||||||
|
BAUDRATE_RANGE(dev->baudrate, 2400, 4800);
|
||||||
|
BAUDRATE_RANGE(dev->baudrate, 4800, 9600);
|
||||||
|
BAUDRATE_RANGE(dev->baudrate, 9600, 14400);
|
||||||
|
BAUDRATE_RANGE(dev->baudrate, 14400, 19200);
|
||||||
|
BAUDRATE_RANGE(dev->baudrate, 19200, 38400);
|
||||||
|
BAUDRATE_RANGE(dev->baudrate, 38400, 57600);
|
||||||
|
BAUDRATE_RANGE(dev->baudrate, 57600, 115200);
|
||||||
|
BAUDRATE_RANGE(dev->baudrate, 115200, 0xFFFFFFFF);
|
||||||
|
|
||||||
|
serialattr.ByteSize = dev->data_bits;
|
||||||
|
serialattr.StopBits = (dev->serial->lcr & 0x04) ? TWOSTOPBITS : ONESTOPBIT;
|
||||||
|
if (!(dev->serial->lcr & 0x08)) {
|
||||||
|
serialattr.fParity = 0;
|
||||||
|
serialattr.Parity = NOPARITY;
|
||||||
|
} else {
|
||||||
|
serialattr.fParity = 1;
|
||||||
|
if (dev->serial->lcr & 0x20) {
|
||||||
|
serialattr.Parity = (MARKPARITY) + !!(dev->serial->lcr & 0x10);
|
||||||
|
} else {
|
||||||
|
serialattr.Parity = (ODDPARITY) + !!(dev->serial->lcr & 0x10);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SetCommState((HANDLE)dev->master_fd, &serialattr);
|
||||||
|
#undef BAUDRATE_RANGE
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
plat_serpt_write(void *p, uint8_t data)
|
||||||
|
{
|
||||||
|
serial_passthrough_t *dev = (serial_passthrough_t *) p;
|
||||||
|
|
||||||
|
switch (dev->mode) {
|
||||||
|
case SERPT_MODE_VCON:
|
||||||
|
case SERPT_MODE_HOSTSER:
|
||||||
|
plat_serpt_write_vcon(dev, data);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t
|
||||||
|
plat_serpt_read_vcon(serial_passthrough_t *dev, uint8_t *data)
|
||||||
|
{
|
||||||
|
DWORD bytesRead = 0;
|
||||||
|
ReadFile((HANDLE) dev->master_fd, data, 1, &bytesRead, NULL);
|
||||||
|
return !!bytesRead;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
plat_serpt_read(void *p, uint8_t *data)
|
||||||
|
{
|
||||||
|
serial_passthrough_t *dev = (serial_passthrough_t *) p;
|
||||||
|
int res = 0;
|
||||||
|
|
||||||
|
switch (dev->mode) {
|
||||||
|
case SERPT_MODE_VCON:
|
||||||
|
case SERPT_MODE_HOSTSER:
|
||||||
|
res = plat_serpt_read_vcon(dev, data);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
open_pseudo_terminal(serial_passthrough_t *dev)
|
||||||
|
{
|
||||||
|
char ascii_pipe_name[1024] = { 0 };
|
||||||
|
snprintf(ascii_pipe_name, sizeof(ascii_pipe_name), "\\\\.\\pipe\\86Box\\%s", vm_name);
|
||||||
|
dev->master_fd = (intptr_t) CreateNamedPipeA(ascii_pipe_name, PIPE_ACCESS_DUPLEX, PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_NOWAIT, 32, 65536, 65536, NMPWAIT_USE_DEFAULT_WAIT, NULL);
|
||||||
|
if (dev->master_fd == (intptr_t) INVALID_HANDLE_VALUE) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
pclog("Named Pipe @ %s\n", ascii_pipe_name);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
open_host_serial_port(serial_passthrough_t *dev)
|
||||||
|
{
|
||||||
|
COMMTIMEOUTS timeouts = {
|
||||||
|
.ReadIntervalTimeout = MAXDWORD,
|
||||||
|
.ReadTotalTimeoutConstant = 0,
|
||||||
|
.ReadTotalTimeoutMultiplier = 0,
|
||||||
|
.WriteTotalTimeoutMultiplier = 0,
|
||||||
|
.WriteTotalTimeoutConstant = 1000
|
||||||
|
};
|
||||||
|
DCB* serialattr = calloc(1, sizeof(DCB));
|
||||||
|
if (!serialattr) return 0;
|
||||||
|
dev->master_fd = (intptr_t) CreateFileA(dev->host_serial_path, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);
|
||||||
|
if (dev->master_fd == (intptr_t) INVALID_HANDLE_VALUE) {
|
||||||
|
free(serialattr);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if (!SetCommTimeouts((HANDLE) dev->master_fd, &timeouts)) {
|
||||||
|
pclog(LOG_PREFIX "error setting COM port timeouts.\n");
|
||||||
|
CloseHandle((HANDLE) dev->master_fd);
|
||||||
|
free(serialattr);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
GetCommState((HANDLE)dev->master_fd, serialattr);
|
||||||
|
dev->backend_priv = serialattr;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
plat_serpt_open_device(void *p)
|
||||||
|
{
|
||||||
|
serial_passthrough_t *dev = (serial_passthrough_t *) p;
|
||||||
|
|
||||||
|
switch (dev->mode) {
|
||||||
|
case SERPT_MODE_VCON:
|
||||||
|
if (open_pseudo_terminal(dev)) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case SERPT_MODE_HOSTSER:
|
||||||
|
if (open_host_serial_port(dev)) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
@@ -71,6 +71,7 @@
|
|||||||
#include <86box/plat.h>
|
#include <86box/plat.h>
|
||||||
#include <86box/ui.h>
|
#include <86box/ui.h>
|
||||||
#include <86box/win.h>
|
#include <86box/win.h>
|
||||||
|
#include <86box/serial_passthrough.h>
|
||||||
#include "../disk/minivhd/minivhd.h"
|
#include "../disk/minivhd/minivhd.h"
|
||||||
#include "../disk/minivhd/minivhd_util.h"
|
#include "../disk/minivhd/minivhd_util.h"
|
||||||
|
|
||||||
@@ -111,6 +112,7 @@ static char temp_pcap_dev[NET_CARD_MAX][128];
|
|||||||
/* Ports category */
|
/* Ports category */
|
||||||
static int temp_lpt_devices[PARALLEL_MAX];
|
static int temp_lpt_devices[PARALLEL_MAX];
|
||||||
static int temp_serial[SERIAL_MAX], temp_lpt[PARALLEL_MAX];
|
static int temp_serial[SERIAL_MAX], temp_lpt[PARALLEL_MAX];
|
||||||
|
static int temp_serial_passthrough_enabled[SERIAL_MAX];
|
||||||
|
|
||||||
/* Other peripherals category */
|
/* Other peripherals category */
|
||||||
static int temp_fdc_card, temp_hdc, temp_ide_ter, temp_ide_qua, temp_cassette;
|
static int temp_fdc_card, temp_hdc, temp_ide_ter, temp_ide_qua, temp_cassette;
|
||||||
@@ -361,8 +363,10 @@ win_settings_init(void)
|
|||||||
temp_lpt_devices[i] = lpt_ports[i].device;
|
temp_lpt_devices[i] = lpt_ports[i].device;
|
||||||
temp_lpt[i] = lpt_ports[i].enabled;
|
temp_lpt[i] = lpt_ports[i].enabled;
|
||||||
}
|
}
|
||||||
for (i = 0; i < SERIAL_MAX; i++)
|
for (i = 0; i < SERIAL_MAX; i++) {
|
||||||
temp_serial[i] = com_ports[i].enabled;
|
temp_serial[i] = com_ports[i].enabled;
|
||||||
|
temp_serial_passthrough_enabled[i] = serial_passthrough_enabled[i];
|
||||||
|
}
|
||||||
|
|
||||||
/* Storage devices category */
|
/* Storage devices category */
|
||||||
for (i = 0; i < SCSI_BUS_MAX; i++)
|
for (i = 0; i < SCSI_BUS_MAX; i++)
|
||||||
@@ -484,8 +488,10 @@ win_settings_changed(void)
|
|||||||
i = i || (temp_lpt_devices[j] != lpt_ports[j].device);
|
i = i || (temp_lpt_devices[j] != lpt_ports[j].device);
|
||||||
i = i || (temp_lpt[j] != lpt_ports[j].enabled);
|
i = i || (temp_lpt[j] != lpt_ports[j].enabled);
|
||||||
}
|
}
|
||||||
for (j = 0; j < SERIAL_MAX; j++)
|
for (j = 0; j < SERIAL_MAX; j++) {
|
||||||
i = i || (temp_serial[j] != com_ports[j].enabled);
|
i = i || (temp_serial[j] != com_ports[j].enabled);
|
||||||
|
i = i || (temp_serial_passthrough_enabled[i] != serial_passthrough_enabled[i]);
|
||||||
|
}
|
||||||
|
|
||||||
/* Storage devices category */
|
/* Storage devices category */
|
||||||
for (j = 0; j < SCSI_BUS_MAX; j++)
|
for (j = 0; j < SCSI_BUS_MAX; j++)
|
||||||
@@ -578,8 +584,10 @@ win_settings_save(void)
|
|||||||
lpt_ports[i].device = temp_lpt_devices[i];
|
lpt_ports[i].device = temp_lpt_devices[i];
|
||||||
lpt_ports[i].enabled = temp_lpt[i];
|
lpt_ports[i].enabled = temp_lpt[i];
|
||||||
}
|
}
|
||||||
for (i = 0; i < SERIAL_MAX; i++)
|
for (i = 0; i < SERIAL_MAX; i++) {
|
||||||
com_ports[i].enabled = temp_serial[i];
|
com_ports[i].enabled = temp_serial[i];
|
||||||
|
serial_passthrough_enabled[i] = temp_serial_passthrough_enabled[i];
|
||||||
|
}
|
||||||
|
|
||||||
/* Storage devices category */
|
/* Storage devices category */
|
||||||
for (i = 0; i < SCSI_BUS_MAX; i++)
|
for (i = 0; i < SCSI_BUS_MAX; i++)
|
||||||
@@ -1764,8 +1772,10 @@ win_settings_ports_proc(HWND hdlg, UINT message, WPARAM wParam, LPARAM lParam)
|
|||||||
settings_enable_window(hdlg, IDC_COMBO_LPT1 + i, temp_lpt[i]);
|
settings_enable_window(hdlg, IDC_COMBO_LPT1 + i, temp_lpt[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i < SERIAL_MAX; i++)
|
for (i = 0; i < SERIAL_MAX; i++) {
|
||||||
settings_set_check(hdlg, IDC_CHECK_SERIAL1 + i, temp_serial[i]);
|
settings_set_check(hdlg, IDC_CHECK_SERIAL1 + i, temp_serial[i]);
|
||||||
|
settings_set_check(hdlg, IDC_CHECK_SERIAL_PASS1 + i, temp_serial_passthrough_enabled[i]);
|
||||||
|
}
|
||||||
|
|
||||||
free(lptsTemp);
|
free(lptsTemp);
|
||||||
|
|
||||||
@@ -1790,8 +1800,10 @@ win_settings_ports_proc(HWND hdlg, UINT message, WPARAM wParam, LPARAM lParam)
|
|||||||
temp_lpt[i] = settings_get_check(hdlg, IDC_CHECK_PARALLEL1 + i);
|
temp_lpt[i] = settings_get_check(hdlg, IDC_CHECK_PARALLEL1 + i);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i < SERIAL_MAX; i++)
|
for (i = 0; i < SERIAL_MAX; i++) {
|
||||||
temp_serial[i] = settings_get_check(hdlg, IDC_CHECK_SERIAL1 + i);
|
temp_serial[i] = settings_get_check(hdlg, IDC_CHECK_SERIAL1 + i);
|
||||||
|
temp_serial_passthrough_enabled[i] = settings_get_check(hdlg, IDC_CHECK_SERIAL_PASS1 + i);
|
||||||
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|||||||
@@ -2,8 +2,8 @@
|
|||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <Windows.h>
|
#include <windows.h>
|
||||||
#include <CommCtrl.h>
|
#include <commctrl.h>
|
||||||
#include <86box/86box.h>
|
#include <86box/86box.h>
|
||||||
#include <86box/plat.h>
|
#include <86box/plat.h>
|
||||||
#include <86box/resource.h>
|
#include <86box/resource.h>
|
||||||
|
|||||||
Reference in New Issue
Block a user