Merge remote-tracking branch 'upstream/master' into qt-wacom-serial

This commit is contained in:
Cacodemon345
2023-02-15 11:12:25 +06:00
66 changed files with 2938 additions and 710 deletions

View File

@@ -26,7 +26,6 @@
# - Packaging the Ghostscript DLL requires 32-bit and/or 64-bit Ghostscript on Program Files
# - Packaging the FluidSynth DLL requires it to be at /home/86Box/dll32/libfluidsynth.dll
# and/or /home/86Box/dll64/libfluidsynth64.dll (for 32-bit and 64-bit builds respectively)
# - Packaging the Discord DLL requires wget (MSYS should come with it)
# - For Linux builds:
# - Only Debian and derivatives are supported
# - dpkg and apt-get are called through sudo to manage dependencies; make sure those
@@ -284,7 +283,7 @@ then
then
# Update keyring as well, since the package signing keys sometimes change.
echo [-] Updating package databases and keyring
yes | pacman -Sy --needed msys2-keyring
pacman -Sy --needed --noconfirm msys2-keyring
# Save build tag to skip pacman sync/keyring later.
save_buildtag pacmansync
@@ -292,100 +291,29 @@ then
echo [-] Not updating package databases and keyring again
fi
# Query installed packages.
pacman -Qe > "$cache_dir/pacman.txt"
# Download the specified versions of architecture-specific dependencies.
echo -n [-] Downloading dependencies:
pkg_dir="/var/cache/pacman/pkg"
repo_base="https://repo.msys2.org/mingw/$(echo $MSYSTEM | tr '[:upper:]' '[:lower:]')"
cat .ci/dependencies_msys.txt | tr -d '\r' > "$cache_dir/deps.txt"
pkgs=""
while IFS=" " read pkg version
do
prefixed_pkg="$MINGW_PACKAGE_PREFIX-$pkg"
installed_version=$(grep -E "^$prefixed_pkg " "$cache_dir/pacman.txt" | cut -d " " -f 2)
if [ "$installed_version" != "$version" ] # installed_version will be empty if not installed
then
echo -n " [$pkg"
# Download package if not already present in the local cache.
pkg_tar="$prefixed_pkg-$version-any.pkg.tar"
if [ -s "$pkg_dir/$pkg_tar.xz" ]
then
pkg_fn="$pkg_tar.xz"
pkg_dest="$pkg_dir/$pkg_fn"
else
pkg_fn="$pkg_tar.zst"
pkg_dest="$pkg_dir/$pkg_fn"
if [ ! -s "$pkg_dest" ]
then
if ! wget -qO "$pkg_dest" "$repo_base/$pkg_fn"
then
rm -f "$pkg_dest"
pkg_fn="$pkg_tar.xz"
pkg_dest="$pkg_dir/$pkg_fn"
wget -qO "$pkg_dest" "$repo_base/$pkg_fn" || rm -f "$pkg_dest"
fi
if [ -s "$pkg_dest" ]
then
wget -qO "$pkg_dest.sig" "$repo_base/$pkg_fn.sig" || rm -f "$pkg_dest.sig"
[ ! -s "$pkg_dest.sig" ] && rm -f "$pkg_dest.sig"
fi
fi
fi
# Check if the cached package is valid.
if [ -s "$pkg_dest" ]
then
# Add cached zst package.
pkgs="$pkgs $pkg_fn"
else
# Not valid, remove if it exists.
rm -f "$pkg_dest" "$pkg_dest.sig"
echo -n " FAIL"
fi
echo -n "]"
fi
done < "$cache_dir/deps.txt"
[ -z "$pkgs" ] && echo -n ' none required'
echo
# Install the downloaded architecture-specific dependencies.
echo [-] Installing dependencies through pacman
if [ -n "$pkgs" ]
then
pushd "$pkg_dir"
yes | pacman -U --needed $pkgs
if [ $? -ne 0 ]
then
# Install packages individually if installing them all together failed.
for pkg in $pkgs
do
yes | pacman -U --needed "$pkg"
done
fi
popd
# Query installed packages again.
pacman -Qe > "$cache_dir/pacman.txt"
fi
# Install the latest versions for any missing packages (if the specified version couldn't be installed).
# Establish general dependencies.
pkgs="git"
while IFS=" " read pkg version
# Gather installed architecture-specific packages for updating.
# This prevents outdated shared libraries, unmet dependencies
# and potentially other issues caused by the fact pacman doesn't
# update a package's dependencies unless explicitly told to.
pkgs="$pkgs $(pacman -Quq | grep -E "^$MINGW_PACKAGE_PREFIX-")"
# Establish architecture-specific dependencies.
while read pkg rest
do
prefixed_pkg="$MINGW_PACKAGE_PREFIX-$pkg"
grep -qE "^$prefixed_pkg " "$cache_dir/pacman.txt" || pkgs="$pkgs $prefixed_pkg"
done < "$cache_dir/deps.txt"
rm -f "$cache_dir/pacman.txt" "$cache_dir/deps.txt"
yes | pacman -S --needed $pkgs
if [ $? -ne 0 ]
pkgs="$pkgs $MINGW_PACKAGE_PREFIX-$(echo "$pkg" | tr -d '\r')" # CR removal required
done < .ci/dependencies_msys.txt
# Install or update dependencies.
echo [-] Installing dependencies through pacman
if ! pacman -S --needed --noconfirm $pkgs
then
# Install packages individually if installing them all together failed.
for pkg in $pkgs
do
yes | pacman -S --needed "$pkg"
pacman -S --needed --noconfirm "$pkg"
done
fi

View File

@@ -1,24 +1,12 @@
zlib 1.2.11-9
binutils 2.37-4
headers-git 9.0.0.6357.eac8c38c1-1
crt-git 9.0.0.6357.eac8c38c1-2
libwinpthread-git 9.0.0.6357.eac8c38c1-1
winpthreads-git 9.0.0.6357.eac8c38c1-1
winstorecompat-git 9.0.0.6357.eac8c38c1-1
gcc-libs 11.2.0-4
gcc-ada 11.2.0-4
gcc-fortran 11.2.0-4
gcc-libgfortran 11.2.0-4
gcc-objc 11.2.0-4
gcc 11.2.0-4
libgccjit 11.2.0-4
tools-git 9.0.0.6357.eac8c38c1-1
ninja 1.10.2-3
pkgconf 1.8.0-2
openal 1.21.1-3
libpng 1.6.37-6
freetype 2.11.1-1
SDL2 2.0.18-2
rtmidi 4.0.0-1
cmake 3.22.1-1
qt5-static 5.15.2-4
ninja
cmake
gcc
pkgconf
openal
freetype
SDL2
zlib
libpng
rtmidi
qt5-static
qt5-translations

View File

@@ -19,11 +19,14 @@
* Copyright 2017-2020 Fred N. van Kempen.
* Copyright 2021 Laci bá'
* Copyright 2021 dob205
* Copyright 2021 Andreas J. Reichel.
* Copyright 2021-2022 Jasmine Iwanek.
*/
#include <inttypes.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdint.h>
#include <stdbool.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
@@ -68,6 +71,7 @@
#include <86box/isartc.h>
#include <86box/lpt.h>
#include <86box/serial.h>
#include <86box/serial_passthrough.h>
#include <86box/keyboard.h>
#include <86box/mouse.h>
#include <86box/gameport.h>
@@ -162,6 +166,7 @@ int video_filter_method = 1; /* (C) video */
int video_vsync = 0; /* (C) video */
int video_framerate = -1; /* (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 postcard_enabled = 0; /* (C) enable POST card */
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. */
serial_standalone_init();
serial_passthrough_init();
/* Reset and reconfigure the Sound Card layer. */
sound_card_reset();

View File

@@ -851,9 +851,28 @@ pipc_sb_handlers(pipc_t *dev, uint8_t modem)
if (dev->ac97_regs[0][0x42] & 0x04) {
io_sethandler(0x388, 4, pipc_fm_read, NULL, NULL, pipc_fm_write, NULL, NULL, dev);
#ifndef VIA_PIPC_FM_EMULATION
dev->sb->opl_enabled = 1;
} else {
dev->sb->opl_enabled = 0;
#endif
}
}
static void
pipc_sb_get_buffer(int32_t *buffer, int len, void *priv)
{
pipc_t *dev = (pipc_t *) priv;
/* Poll SB audio only if the legacy block is enabled. */
#ifdef VIA_PIPC_FM_EMULATION
if (dev->ac97_regs[0][0x42] & 0x01)
#else
if (dev->ac97_regs[0][0x42] & 0x05)
#endif
sb_get_buffer_sbpro(buffer, len, dev->sb);
}
static uint8_t
pipc_read(int func, int addr, void *priv)
{
@@ -1599,10 +1618,7 @@ pipc_init(const device_t *info)
ac97_via_set_slot(dev->ac97, dev->slot, PCI_INTC);
dev->sb = device_add_inst(&sb_pro_compat_device, 2);
#ifndef VIA_PIPC_FM_EMULATION
dev->sb->opl_enabled = 1;
#endif
sound_add_handler(sb_get_buffer_sbpro, dev->sb);
sound_add_handler(pipc_sb_get_buffer, dev);
dev->gameport = gameport_add(&gameport_sio_device);

View File

@@ -20,6 +20,8 @@
* Copyright 2016-2019 Miran Grca.
* Copyright 2017-2019 Fred N. van Kempen.
* 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
* it on Windows XP, and possibly also Vista. Use the
@@ -54,6 +56,8 @@
#include <86box/fdc.h>
#include <86box/fdc_ext.h>
#include <86box/gameport.h>
#include <86box/serial.h>
#include <86box/serial_passthrough.h>
#include <86box/machine.h>
#include <86box/mouse.h>
#include <86box/thread.h>
@@ -81,6 +85,7 @@ static ini_t config;
static int backwards_compat = 0;
static int backwards_compat2 = 0;
#define ENABLE_CONFIG_LOG 1
#ifdef ENABLE_CONFIG_LOG
int config_do_log = ENABLE_CONFIG_LOG;
@@ -836,6 +841,8 @@ load_ports(void)
char temp[512];
int c, d;
memset(temp, 0, sizeof(temp));
for (c = 0; c < SERIAL_MAX; c++) {
sprintf(temp, "serial%d_enabled", c + 1);
com_ports[c].enabled = !!ini_section_get_int(cat, temp, (c >= 2) ? 0 : 1);
@@ -845,6 +852,12 @@ load_ports(void)
p = (char *) ini_section_get_string(cat, temp, "none");
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++) {
@@ -2466,6 +2479,12 @@ save_ports(void)
ini_section_set_string(cat, temp,
(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++) {

View File

@@ -18,6 +18,8 @@
* Copyright 2017-2019 Fred N. van Kempen.
* Copyright 2016-2019 Miran Grca.
* 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
* 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));
c->dev = d;
c->instance = inst;
if (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 *
device_get_config_string(const char *s)
{
@@ -748,7 +757,7 @@ device_is_valid(const device_t *device, int m)
int
machine_get_config_int(char *s)
{
const device_t *d = machine_getdevice(machine);
const device_t *d = machine_get_device(machine);
const device_config_t *c;
if (d == NULL)
@@ -768,7 +777,7 @@ machine_get_config_int(char *s)
char *
machine_get_config_string(char *s)
{
const device_t *d = machine_getdevice(machine);
const device_t *d = machine_get_device(machine);
const device_config_t *c;
if (d == NULL)

View File

@@ -11,6 +11,8 @@
# Authors: David Hrdlička, <hrdlickadavid@outlook.com>
#
# 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
@@ -18,7 +20,7 @@ add_library(dev OBJECT bugger.c cassette.c cartridge.c hasp.c hwm.c hwm_lm75.c h
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
mouse.c mouse_bus.c mouse_serial.c mouse_ps2.c phoenix_486_jumper.c
mouse_wacom_tablet.c)
mouse_wacom_tablet.c serial_passthrough.c)
if(ISAMEM_RAMPAGE)
target_compile_definitions(dev PRIVATE USE_ISAMEM_RAMPAGE)

View File

@@ -191,6 +191,12 @@ ps2_write(uint8_t val, void *priv)
keyboard_at_adddata_mouse(dev->sample_rate);
break;
case 0xea: /* set stream */
dev->flags &= ~FLAG_CTRLDAT;
mouse_scan = 1;
keyboard_at_adddata_mouse(0xfa); /* ACK for command byte */
break;
case 0xeb: /* Get mouse data */
keyboard_at_adddata_mouse(0xfa);

View File

@@ -93,6 +93,8 @@ serial_transmit_period(serial_t *dev)
/* Bit period based on DLAB. */
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
@@ -161,7 +163,7 @@ write_fifo(serial_t *dev, uint8_t dat)
dev->lsr |= 0x01;
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++;
else
dev->rcvr_fifo_full = 1;
@@ -175,6 +177,8 @@ write_fifo(serial_t *dev, uint8_t dat)
dev->dat = dat;
dev->lsr |= 0x01;
dev->int_status |= SERIAL_INT_RECEIVE;
if (dev->lsr & 0x02)
dev->int_status |= SERIAL_INT_LSR;
serial_update_ints(dev);
}
}
@@ -311,6 +315,22 @@ serial_timeout_timer(void *priv)
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
serial_update_speed(serial_t *dev)
{
@@ -331,6 +351,63 @@ serial_reset_fifo(serial_t *dev)
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
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:
old = dev->lcr;
dev->lcr = val;
if ((old ^ val) & 0x0f) {
if ((old ^ val) & 0x3f) {
/* Data bits + start bit. */
dev->bits = ((dev->lcr & 0x03) + 5) + 1;
/* Stop bits. */
@@ -444,11 +521,14 @@ serial_write(uint16_t addr, uint8_t val, void *p)
serial_transmit_period(dev);
serial_update_speed(dev);
if (dev->sd && dev->sd->lcr_callback)
dev->sd->lcr_callback(dev, dev->sd->priv, dev->lcr);
}
break;
case 4:
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);
}
if (!(val & 8) && (dev->mctrl & 8))
@@ -487,7 +567,7 @@ serial_write(uint16_t addr, uint8_t val, void *p)
serial_update_ints(dev);
break;
case 6:
dev->msr = val;
dev->msr = (val & 0xF0) | (dev->msr & 0x0F);
if (dev->msr & 0x0f)
dev->int_status |= SERIAL_INT_MSR;
serial_update_ints(dev);
@@ -521,11 +601,15 @@ serial_read(uint16_t addr, void *p)
ret = dev->rcvr_fifo[0];
dev->rcvr_fifo_full = 0;
for (i = 1; i < 16; i++)
dev->rcvr_fifo[i - 1] = dev->rcvr_fifo[i];
dev->rcvr_fifo_pos--;
if (dev->rcvr_fifo_pos > 0) {
for (i = 1; i < 16; 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--;
/* At least one byte remains to be read, start the timeout
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);
@@ -571,7 +655,7 @@ serial_read(uint16_t addr, void *p)
serial_update_ints(dev);
break;
case 6:
ret = dev->msr;
ret = dev->msr | dev->msr_set;
dev->msr &= ~0x0f;
dev->int_status &= ~SERIAL_INT_MSR;
serial_update_ints(dev);
@@ -630,9 +714,30 @@ serial_attach(int port,
{
serial_device_t *sd = &serial_devices[port];
sd->rcr_callback = rcr_callback;
sd->dev_write = dev_write;
sd->priv = priv;
sd->rcr_callback = rcr_callback;
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;
return sd->serial;
}

View 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
};

View File

@@ -60,7 +60,7 @@ enum {
CDROM_BUS_USB
};
#define KNOWN_CDROM_DRIVE_TYPES 30
#define KNOWN_CDROM_DRIVE_TYPES 35
#define BUS_TYPE_ALL 0
#define BUS_TYPE_IDE 1
#define BUS_TYPE_SCSI 2
@@ -75,36 +75,41 @@ static const struct
const int bus_type;
} cdrom_drive_types[] =
{
{ "86BOX", "CD-ROM", "1.00", "(ATAPI/SCSI) 86BOX CD-ROM 1.00", "86BOX_CD-ROM_1.00", BUS_TYPE_ALL},
{ "AZT", "CDA46802I", "1.15", "(ATAPI) AZT CDA46802I 1.15", "AZT_CDA46802I_1.15", BUS_TYPE_IDE},
{ "BTC", "CD-ROM BCD36XH", "U1.0", "(ATAPI) BTC CD-ROM BCD36XH U1.0", "BTC_CD-ROM_BCD36XH_U1.0", BUS_TYPE_IDE},
{ "GOLDSTAR", "CRD-8160B", "3.14", "(ATAPI) GOLDSTAR CRD-8160B 3.14", "GOLDSTAR_CRD-8160B_3.14", BUS_TYPE_IDE},
{ "HITACHI", "CDR-8130", "0020", "(ATAPI) HITACHI CDR-8130 0020", "HITACHI_CDR-8130_0020", BUS_TYPE_IDE},
{ "KENWOOD", "CD-ROM UCR-421", "208E", "(ATAPI) KENWOOD CD-ROM UCR-421 208E", "KENWOOD_CD-ROM_UCR-421_208E", BUS_TYPE_IDE},
{ "MATSHITA", "CD-ROM CR-587", "7S13", "(ATAPI) MATSHITA CD-ROM CR-587 7S13", "MATSHITA_CD-ROM_CR-587_7S13", BUS_TYPE_IDE},
{ "MATSHITA", "CD-ROM CR-588", "LS15", "(ATAPI) MATSHITA CD-ROM CR-588 LS15", "MATSHITA_CD-ROM_CR-588_LS15", BUS_TYPE_IDE},
{ "MITSUMI", "CRMC-FX4820T", "D02A", "(ATAPI) MITSUMI CRMC-FX4820T D02A", "MITSUMI_CRMC-FX4820T_D02A", BUS_TYPE_IDE},
{ "NEC", "CD-ROM DRIVE:260", "1.00", "(ATAPI) NEC CD-ROM DRIVE:260 1.00", "NEC_CD-ROM_DRIVE260_1.00", BUS_TYPE_IDE},
{ "NEC", "CD-ROM DRIVE:260", "1.01", "(ATAPI) NEC CD-ROM DRIVE:260 1.01", "NEC_CD-ROM_DRIVE260_1.01", BUS_TYPE_IDE},
{ "NEC", "CDR-1300A", "1.05", "(ATAPI) NEC CDR-1300A 1.05", "NEC_CDR-1300A_1.05", BUS_TYPE_IDE},
{ "PHILIPS", "CD-ROM PCA403CD", "U31P", "(ATAPI) PHILIPS CD-ROM PCA403CD U31P", "PHILIPS_CD-ROM_PCA403CD_U31P", BUS_TYPE_IDE},
{ "SONY", "CD-ROM CDU76", "1.0i", "(ATAPI) SONY CD-ROM CDU76 1.0i", "SONY_CD-ROM_CDU76_1.0i", BUS_TYPE_IDE},
{ "SONY", "CD-ROM CDU311", "3.0h", "(ATAPI) SONY CD-ROM CDU311 3.0h", "SONY_CD-ROM_CDU311_3.0h", BUS_TYPE_IDE},
{ "TOSHIBA", "CD-ROM XM-5702B", "TA70", "(ATAPI) TOSHIBA CD-ROM XM-5702B TA70", "TOSHIBA_CD-ROM_XM-5702B_TA70", BUS_TYPE_IDE},
{ "CHINON", "CD-ROM CDS-431", "H42 ", "(SCSI) CHINON CD-ROM CDS-431 H42", "CHINON_CD-ROM_CDS-431_H42", BUS_TYPE_SCSI},
{ "DEC", "RRD45 (C) DEC", "0436", "(SCSI) DEC RRD45 0436", "DEC_RRD45_0436", BUS_TYPE_SCSI},
{ "MATSHITA", "CD-ROM CR-501", "1.0b", "(SCSI) MATSHITA CD-ROM CR-501 1.0b", "MATSHITA_CD-ROM_CR-501_1.0b", BUS_TYPE_SCSI},
{ "NEC", "CD-ROM DRIVE:74", "1.00", "(SCSI) NEC CD-ROM DRIVE:74 1.00", "NEC_CD-ROM_DRIVE74_1.00", BUS_TYPE_SCSI},
{ "NEC", "CD-ROM DRIVE:464", "1.05", "(SCSI) NEC CD-ROM DRIVE:464 1.05", "NEC_CD-ROM_DRIVE464_1.05", BUS_TYPE_SCSI},
{ "SONY", "CD-ROM CDU-541", "1.0i", "(SCSI) SONY CD-ROM CDU-541 1.0i", "SONY_CD-ROM_CDU-541_1.0i", BUS_TYPE_SCSI},
{ "SONY", "CD-ROM CDU-76S", "1.00", "(SCSI) SONY CD-ROM CDU-76S 1.00", "SONY_CD-ROM_CDU-76S_1.00", BUS_TYPE_SCSI},
{ "PHILIPS", "CDD2600", "1.07", "(SCSI) PHILIPS CDD2600 1.07", "PHILIPS_CDD2600_1.07", BUS_TYPE_SCSI},
{ "PIONEER", "CD-ROM DRM-604X", "2403", "(SCSI) PIONEER CD-ROM DRM-604X 2403", "PIONEER_CD-ROM_DRM-604X_2403", BUS_TYPE_SCSI},
{ "PLEXTOR", "CD-ROM PX-32TS", "1.03", "(SCSI) PLEXTOR CD-ROM PX-32TS 1.03", "PLEXTOR_CD-ROM_PX-32TS_1.03", BUS_TYPE_SCSI},
{ "TEAC", "CD-R55S", "1.0R", "(SCSI) TEAC CD-R55S 1.0R", "TEAC_CD-R55S_1.0R", BUS_TYPE_SCSI},
{ "TOSHIBA", "CD-ROM DRIVE:XM", "3433", "(SCSI) TOSHIBA CD-ROM DRIVE:XM 3433", "TOSHIBA_CD-ROM_DRIVEXM_3433", BUS_TYPE_SCSI},
{ "TOSHIBA", "CD-ROM XM-3301TA", "0272", "(SCSI) TOSHIBA CD-ROM XM-3301TA 0272", "TOSHIBA_CD-ROM_XM-3301TA_0272", BUS_TYPE_SCSI},
{ "TOSHIBA", "CD-ROM XM-5701TA", "3136", "(SCSI) TOSHIBA CD-ROM XM-5701TA 3136", "TOSHIBA_CD-ROM_XM-5701TA_3136", BUS_TYPE_SCSI},
{ "86BOX", "CD-ROM", "1.00", "(ATAPI/SCSI) 86BOX CD-ROM 1.00", "86BOX_CD-ROM_1.00", BUS_TYPE_ALL}, /*1*/
{ "AZT", "CDA46802I", "1.15", "(ATAPI) AZT CDA46802I 1.15", "AZT_CDA46802I_1.15", BUS_TYPE_IDE}, /*2*/
{ "BTC", "CD-ROM BCD36XH", "U1.0", "(ATAPI) BTC CD-ROM BCD36XH U1.0", "BTC_CD-ROM_BCD36XH_U1.0", BUS_TYPE_IDE}, /*3*/
{ "GOLDSTAR", "CRD-8160B", "3.14", "(ATAPI) GOLDSTAR CRD-8160B 3.14", "GOLDSTAR_CRD-8160B_3.14", BUS_TYPE_IDE}, /*4*/
{ "HITACHI", "CDR-8130", "0020", "(ATAPI) HITACHI CDR-8130 0020", "HITACHI_CDR-8130_0020", BUS_TYPE_IDE}, /*5*/
{ "KENWOOD", "CD-ROM UCR-421", "208E", "(ATAPI) KENWOOD CD-ROM UCR-421 208E", "KENWOOD_CD-ROM_UCR-421_208E", BUS_TYPE_IDE}, /*6*/
{ "MATSHITA", "CD-ROM CR-587", "7S13", "(ATAPI) MATSHITA CD-ROM CR-587 7S13", "MATSHITA_CD-ROM_CR-587_7S13", BUS_TYPE_IDE}, /*7*/
{ "MATSHITA", "CD-ROM CR-588", "LS15", "(ATAPI) MATSHITA CD-ROM CR-588 LS15", "MATSHITA_CD-ROM_CR-588_LS15", BUS_TYPE_IDE}, /*8*/
{ "MATSHITA", "CR-571", "1.0e", "(ATAPI) MATSHITA CR-571 1.0e", "MATSHITA_CR-571_1.0e", BUS_TYPE_IDE}, /*9*/
{ "MATSHITA", "CR-572", "1.0j", "(ATAPI) MATSHITA CR-572 1.0j", "MATSHITA_CR-572_1.0j", BUS_TYPE_IDE}, /*10*/
{ "MITSUMI", "CRMC-FX4820T", "D02A", "(ATAPI) MITSUMI CRMC-FX4820T D02A", "MITSUMI_CRMC-FX4820T_D02A", BUS_TYPE_IDE}, /*11*/
{ "NEC", "CD-ROM DRIVE:260", "1.00", "(ATAPI) NEC CD-ROM DRIVE:260 1.00", "NEC_CD-ROM_DRIVE260_1.00", BUS_TYPE_IDE}, /*12*/
{ "NEC", "CD-ROM DRIVE:260", "1.01", "(ATAPI) NEC CD-ROM DRIVE:260 1.01", "NEC_CD-ROM_DRIVE260_1.01", BUS_TYPE_IDE}, /*13*/
{ "NEC", "CD-ROM DRIVE:273", "4.20", "(ATAPI) NEC CD-ROM DRIVE:273 4.20", "NEC_CD-ROM_DRIVE273_4.20", BUS_TYPE_IDE}, /*14*/
{ "NEC", "CD-ROM DRIVE:280", "1.05", "(ATAPI) NEC CD-ROM DRIVE:280 1.05", "NEC_CD-ROM_DRIVE280_1.05", BUS_TYPE_IDE}, /*15*/
{ "NEC", "CD-ROM DRIVE:280", "3.08", "(ATAPI) NEC CD-ROM DRIVE:280 3.08", "NEC_CD-ROM_DRIVE280_3.08", BUS_TYPE_IDE}, /*16*/
{ "PHILIPS", "CD-ROM PCA403CD", "U31P", "(ATAPI) PHILIPS CD-ROM PCA403CD U31P", "PHILIPS_CD-ROM_PCA403CD_U31P", BUS_TYPE_IDE}, /*17*/
{ "SONY", "CD-ROM CDU76", "1.0i", "(ATAPI) SONY CD-ROM CDU76 1.0i", "SONY_CD-ROM_CDU76_1.0i", BUS_TYPE_IDE}, /*18*/
{ "SONY", "CD-ROM CDU311", "3.0h", "(ATAPI) SONY CD-ROM CDU311 3.0h", "SONY_CD-ROM_CDU311_3.0h", BUS_TYPE_IDE}, /*19*/
{ "TOSHIBA", "CD-ROM XM-5302TA", "0305", "(ATAPI) TOSHIBA CD-ROM XM-5302TA 0305", "TOSHIBA_CD-ROM_XM-5302TA_0305", BUS_TYPE_IDE}, /*20*/
{ "TOSHIBA", "CD-ROM XM-5702B", "TA70", "(ATAPI) TOSHIBA CD-ROM XM-5702B TA70", "TOSHIBA_CD-ROM_XM-5702B_TA70", BUS_TYPE_IDE}, /*21*/
{ "CHINON", "CD-ROM CDS-431", "H42 ", "(SCSI) CHINON CD-ROM CDS-431 H42", "CHINON_CD-ROM_CDS-431_H42", BUS_TYPE_SCSI}, /*22*/
{ "DEC", "RRD45 (C) DEC", "0436", "(SCSI) DEC RRD45 0436", "DEC_RRD45_0436", BUS_TYPE_SCSI}, /*23*/
{ "MATSHITA", "CD-ROM CR-501", "1.0b", "(SCSI) MATSHITA CD-ROM CR-501 1.0b", "MATSHITA_CD-ROM_CR-501_1.0b", BUS_TYPE_SCSI}, /*24*/
{ "NEC", "CD-ROM DRIVE:74", "1.00", "(SCSI) NEC CD-ROM DRIVE:74 1.00", "NEC_CD-ROM_DRIVE74_1.00", BUS_TYPE_SCSI}, /*25*/
{ "NEC", "CD-ROM DRIVE:464", "1.05", "(SCSI) NEC CD-ROM DRIVE:464 1.05", "NEC_CD-ROM_DRIVE464_1.05", BUS_TYPE_SCSI}, /*26*/
{ "SONY", "CD-ROM CDU-541", "1.0i", "(SCSI) SONY CD-ROM CDU-541 1.0i", "SONY_CD-ROM_CDU-541_1.0i", BUS_TYPE_SCSI}, /*27*/
{ "SONY", "CD-ROM CDU-76S", "1.00", "(SCSI) SONY CD-ROM CDU-76S 1.00", "SONY_CD-ROM_CDU-76S_1.00", BUS_TYPE_SCSI}, /*28*/
{ "PHILIPS", "CDD2600", "1.07", "(SCSI) PHILIPS CDD2600 1.07", "PHILIPS_CDD2600_1.07", BUS_TYPE_SCSI}, /*29*/
{ "PIONEER", "CD-ROM DRM-604X", "2403", "(SCSI) PIONEER CD-ROM DRM-604X 2403", "PIONEER_CD-ROM_DRM-604X_2403", BUS_TYPE_SCSI}, /*30*/
{ "PLEXTOR", "CD-ROM PX-32TS", "1.03", "(SCSI) PLEXTOR CD-ROM PX-32TS 1.03", "PLEXTOR_CD-ROM_PX-32TS_1.03", BUS_TYPE_SCSI}, /*31*/
{ "TEAC", "CD-R55S", "1.0R", "(SCSI) TEAC CD-R55S 1.0R", "TEAC_CD-R55S_1.0R", BUS_TYPE_SCSI}, /*32*/
{ "TOSHIBA", "CD-ROM DRIVE:XM", "3433", "(SCSI) TOSHIBA CD-ROM DRIVE:XM 3433", "TOSHIBA_CD-ROM_DRIVEXM_3433", BUS_TYPE_SCSI}, /*33*/
{ "TOSHIBA", "CD-ROM XM-3301TA", "0272", "(SCSI) TOSHIBA CD-ROM XM-3301TA 0272", "TOSHIBA_CD-ROM_XM-3301TA_0272", BUS_TYPE_SCSI}, /*34*/
{ "TOSHIBA", "CD-ROM XM-5701TA", "3136", "(SCSI) TOSHIBA CD-ROM XM-5701TA 3136", "TOSHIBA_CD-ROM_XM-5701TA_3136", BUS_TYPE_SCSI}, /*35*/
{ "", "", "", "", "", -1},
};

View File

@@ -17,6 +17,8 @@
* Copyright 2017-2019 Fred N. van Kempen.
* Copyright 2016-2019 Miran Grca.
* 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
* it under the terms of the GNU General Public License as published by
@@ -52,6 +54,7 @@
#define CONFIG_MAC 9
#define CONFIG_MIDI_IN 10
#define CONFIG_BIOS 11
#define CONFIG_SERPORT 12
enum {
DEVICE_PCJR = 2, /* requires an IBM PCjr */
@@ -107,7 +110,7 @@ typedef struct {
int default_int;
const char *file_filter;
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];
} device_config_t;
@@ -134,6 +137,7 @@ typedef struct _device_ {
typedef struct {
const device_t *dev;
char name[2048];
int instance;
} device_context_t;
#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_mac(const char *s, int val);
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
extern char *device_get_internal_name(const device_t *d);

View File

@@ -39,8 +39,6 @@ typedef struct {
#define RSHIFT_OFF 0x105
/* KBC #define's */
#define KBC_UNKNOWN 0x0000 /* As yet unknown keyboard */
/* IBM-style controllers */
#define KBC_IBM_PC_XT 0x0000 /* IBM PC/XT */
#define KBC_IBM_PCJR 0x0001 /* IBM PCjr */

View File

@@ -288,7 +288,11 @@ typedef struct _machine_ {
const machine_memory_t ram;
int ram_granularity;
int nvrmask;
uint16_t kbc;
#ifdef EMU_DEVICE_H
const device_t *kbc_device;
#else
void *kbc_device;
#endif /* EMU_DEVICE_H */
/* Bits:
7-0 Set bits are forced set on P1 (no forced set = 0x00);
15-8 Clear bits are forced clear on P1 (no foced clear = 0xff). */
@@ -297,11 +301,15 @@ typedef struct _machine_ {
uint32_t gpio_acpi;
#ifdef EMU_DEVICE_H
const device_t *device;
const device_t *fdc_device;
const device_t *sio_device;
const device_t *vid_device;
const device_t *snd_device;
const device_t *net_device;
#else
void *device;
void *fdc_device;
void *sio_device;
void *vid_device;
void *snd_device;
void *net_device;
@@ -324,10 +332,13 @@ extern char *machine_get_internal_name(void);
extern int machine_get_machine_from_internal_name(char *s);
extern void machine_init(void);
#ifdef EMU_DEVICE_H
extern const device_t *machine_getdevice(int m);
extern const device_t *machine_getviddevice(int m);
extern const device_t *machine_getsnddevice(int m);
extern const device_t *machine_getnetdevice(int m);
extern const device_t *machine_get_kbc_device(int m);
extern const device_t *machine_get_device(int m);
extern const device_t *machine_get_fdc_device(int m);
extern const device_t *machine_get_sio_device(int m);
extern const device_t *machine_get_vid_device(int m);
extern const device_t *machine_get_snd_device(int m);
extern const device_t *machine_get_net_device(int m);
#endif
extern char *machine_get_internal_name_ex(int m);
extern int machine_get_nvrmask(int m);

View File

@@ -1,6 +1,6 @@
#ifndef EMU_PCI_DUMMY_H
#define EMU_PCI_DUMMY_H
extern void pci_dummy_init(void);
extern void pci_dummy_init(int min_slot, int max_slot, int nb_slot, int sb_slot);
#endif /*EMU_PCI_DUMMY_H*/

View 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

View File

@@ -247,6 +247,10 @@
#define IDC_CHECK_PARALLEL2 1089
#define IDC_CHECK_PARALLEL3 1090
#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_COMBO_HDC 1111
@@ -364,6 +368,10 @@
#define IDC_CONFIGURE_NET4 1321
#define IDC_CONFIGURE_MIDI_OUT 1322
#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_JOY2 1331
#define IDC_JOY3 1332

View File

@@ -53,7 +53,7 @@ typedef struct serial_s {
dat, int_status, scratch, fcr,
irq, type, inst, transmit_enabled,
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;
@@ -70,6 +70,8 @@ typedef struct serial_s {
typedef struct serial_device_s {
void (*rcr_callback)(struct serial_s *serial, void *p);
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;
serial_t *serial;
} serial_device_t;
@@ -84,6 +86,12 @@ extern serial_t *serial_attach(int port,
void (*rcr_callback)(struct serial_s *serial, void *p),
void (*dev_write)(struct serial_s *serial, void *p, uint8_t data),
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_set_type(serial_t *dev, int type);
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_set_clock_src(serial_t *dev, double clock_src);
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_pcjr_device;

View 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

View File

@@ -17,7 +17,7 @@
#define WIN_OPENGL_H
#define UNICODE
#include <Windows.h>
#include <windows.h>
extern int opengl_init(HWND hwnd);
extern int opengl_pause(void);

View File

@@ -9,7 +9,7 @@
#define _DISCORD_GAME_SDK_H_
#ifdef _WIN32
#include <Windows.h>
#include <windows.h>
#include <dxgi.h>
#endif

View File

@@ -138,7 +138,7 @@ int
machine_available(int m)
{
int ret;
device_t *d = (device_t *) machine_getdevice(m);
device_t *d = (device_t *) machine_get_device(m);
bios_only = 1;

File diff suppressed because it is too large Load Diff

View File

@@ -1,58 +1,68 @@
/* This can also serve as a sample PCI device. */
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <wchar.h>
#include <86box/86box.h>
#include <86box/device.h>
#include <86box/io.h>
#include <86box/pci.h>
#include <86box/pci_dummy.h>
static uint8_t pci_regs[256];
typedef struct
{
uint8_t pci_regs[256];
static bar_t pci_bar[2];
bar_t pci_bar[2];
static uint8_t interrupt_on = 0x00;
static uint8_t card = 0;
uint8_t card, interrupt_on;
} pci_dummy_t;
static void
pci_dummy_interrupt(int set)
pci_dummy_interrupt(int set, pci_dummy_t *dev)
{
if (set) {
pci_set_irq(card, pci_regs[0x3D]);
} else {
pci_clear_irq(card, pci_regs[0x3D]);
}
if (set)
pci_set_irq(dev->card, PCI_INTA);
else
pci_clear_irq(dev->card, PCI_INTA);
}
static uint8_t
pci_dummy_read(uint16_t Port, void *p)
{
uint8_t ret = 0;
pci_dummy_t *dev = (pci_dummy_t *) p;
uint8_t ret = 0xff;
switch (Port & 0x20) {
case 0x00:
return 0x1A;
ret = 0x1a;
break;
case 0x01:
return 0x07;
ret = 0x07;
break;
case 0x02:
return 0x0B;
ret = 0x0b;
break;
case 0x03:
return 0xAB;
ret = 0xab;
break;
case 0x04:
return pci_regs[0x3C];
ret = dev->pci_regs[0x3c];
break;
case 0x05:
return pci_regs[0x3D];
ret = dev->pci_regs[0x3d];
break;
case 0x06:
ret = interrupt_on;
if (interrupt_on) {
pci_dummy_interrupt(0);
interrupt_on = 0;
ret = dev->interrupt_on;
if (dev->interrupt_on) {
pci_dummy_interrupt(0, dev);
dev->interrupt_on = 0;
}
return ret;
default:
return 0x00;
break;
}
return ret;
}
static uint16_t
@@ -70,15 +80,15 @@ pci_dummy_readl(uint16_t Port, void *p)
static void
pci_dummy_write(uint16_t Port, uint8_t Val, void *p)
{
pci_dummy_t *dev = (pci_dummy_t *) p;
switch (Port & 0x20) {
case 0x06:
if (!interrupt_on) {
interrupt_on = 1;
pci_dummy_interrupt(1);
if (!dev->interrupt_on) {
dev->interrupt_on = 1;
pci_dummy_interrupt(1, dev);
}
return;
default:
return;
break;
}
}
@@ -95,143 +105,179 @@ pci_dummy_writel(uint16_t Port, uint32_t Val, void *p)
}
static void
pci_dummy_io_remove(void)
pci_dummy_io_remove(pci_dummy_t *dev)
{
io_removehandler(pci_bar[0].addr, 0x0020, pci_dummy_read, pci_dummy_readw, pci_dummy_readl, pci_dummy_write, pci_dummy_writew, pci_dummy_writel, NULL);
io_removehandler(dev->pci_bar[0].addr, 0x0020, pci_dummy_read, pci_dummy_readw, pci_dummy_readl, pci_dummy_write, pci_dummy_writew, pci_dummy_writel, dev);
}
static void
pci_dummy_io_set(void)
pci_dummy_io_set(pci_dummy_t *dev)
{
io_sethandler(pci_bar[0].addr, 0x0020, pci_dummy_read, pci_dummy_readw, pci_dummy_readl, pci_dummy_write, pci_dummy_writew, pci_dummy_writel, NULL);
io_sethandler(dev->pci_bar[0].addr, 0x0020, pci_dummy_read, pci_dummy_readw, pci_dummy_readl, pci_dummy_write, pci_dummy_writew, pci_dummy_writel, dev);
}
static uint8_t
pci_dummy_pci_read(int func, int addr, void *priv)
{
pclog("AB0B:071A: PCI_Read(%d, %04x)\n", func, addr);
pci_dummy_t *dev = (pci_dummy_t *) priv;
uint8_t ret = 0xff;
switch (addr) {
case 0x00:
return 0x1A;
case 0x01:
return 0x07;
if (func == 0x00) switch (addr) {
case 0x00: case 0x2c:
ret = 0x1a;
break;
case 0x01: case 0x2d:
ret = 0x07;
break;
case 0x02:
return 0x0B;
case 0x03:
return 0xAB;
case 0x02: case 0x2e:
ret = 0x0b;
break;
case 0x03: case 0x2f:
ret = 0xab;
break;
case 0x04: /* PCI_COMMAND_LO */
case 0x05: /* PCI_COMMAND_HI */
return pci_regs[addr];
case 0x06: /* PCI_STATUS_LO */
case 0x07: /* PCI_STATUS_HI */
return pci_regs[addr];
case 0x0a: case 0x0b:
case 0x3c: /* PCI_ILR */
ret = dev->pci_regs[addr];
break;
case 0x08:
case 0x09:
return 0x00;
case 0x0A:
return pci_regs[addr];
case 0x0B:
return pci_regs[addr];
case 0x08: /* Techncially, revision, but we return the card (slot) here. */
ret = dev->card;
break;
case 0x10: /* PCI_BAR 7:5 */
return (pci_bar[0].addr_regs[0] & 0xe0) | 0x01;
ret = (dev->pci_bar[0].addr_regs[0] & 0xe0) | 0x01;
break;
case 0x11: /* PCI_BAR 15:8 */
return pci_bar[0].addr_regs[1];
case 0x12: /* PCI_BAR 23:16 */
return pci_bar[0].addr_regs[2];
case 0x13: /* PCI_BAR 31:24 */
return pci_bar[0].addr_regs[3];
ret = dev->pci_bar[0].addr_regs[1];
break;
case 0x2C:
return 0x1A;
case 0x2D:
return 0x07;
case 0x2E:
return 0x0B;
case 0x2F:
return 0xAB;
case 0x3C: /* PCI_ILR */
return pci_regs[addr];
case 0x3D: /* PCI_IPR */
return pci_regs[addr];
case 0x3d: /* PCI_IPR */
ret = PCI_INTA;
break;
default:
return 0x00;
ret = 0x00;
break;
}
// pclog("AB0B:071A: PCI_Read(%d, %04X) = %02X\n", func, addr, ret);
return ret;
}
static void
pci_dummy_pci_write(int func, int addr, uint8_t val, void *priv)
{
pci_dummy_t *dev = (pci_dummy_t *) priv;
uint8_t valxor;
pclog("AB0B:071A: PCI_Write(%d, %04x, %02x)\n", func, addr, val);
// pclog("AB0B:071A: PCI_Write(%d, %04X, %02X)\n", func, addr, val);
switch (addr) {
if (func == 0x00) switch (addr) {
case 0x04: /* PCI_COMMAND_LO */
valxor = (val & 0x03) ^ pci_regs[addr];
valxor = (val & 0x03) ^ dev->pci_regs[addr];
if (valxor & PCI_COMMAND_IO) {
pci_dummy_io_remove();
if (((pci_bar[0].addr & 0xffe0) != 0) && (val & PCI_COMMAND_IO)) {
pci_dummy_io_set();
}
pci_dummy_io_remove(dev);
if ((dev->pci_bar[0].addr != 0) && (val & PCI_COMMAND_IO))
pci_dummy_io_set(dev);
}
pci_regs[addr] = val & 0x03;
dev->pci_regs[addr] = val & 0x03;
break;
case 0x10: /* PCI_BAR */
val &= 0xe0; /* 0xe0 acc to RTL DS */
val |= 0x01; /* re-enable IOIN bit */
/*FALLTHROUGH*/
case 0x11: /* PCI_BAR */
case 0x12: /* PCI_BAR */
case 0x13: /* PCI_BAR */
/* Remove old I/O. */
pci_dummy_io_remove();
pci_dummy_io_remove(dev);
/* Set new I/O as per PCI request. */
pci_bar[0].addr_regs[addr & 3] = val;
dev->pci_bar[0].addr_regs[addr & 3] = val;
/* Then let's calculate the new I/O base. */
pci_bar[0].addr &= 0xffe0;
dev->pci_bar[0].addr &= 0xffe0;
/* Log the new base. */
pclog("AB0B:071A: PCI: new I/O base is %04X\n", pci_bar[0].addr);
// pclog("AB0B:071A: PCI: new I/O base is %04X\n", dev->pci_bar[0].addr);
/* We're done, so get out of the here. */
if (pci_regs[4] & PCI_COMMAND_IO) {
if ((pci_bar[0].addr) != 0) {
pci_dummy_io_set();
}
if (dev->pci_regs[4] & PCI_COMMAND_IO) {
if ((dev->pci_bar[0].addr) != 0)
pci_dummy_io_set(dev);
}
break;
case 0x3C: /* PCI_ILR */
pclog("AB0B:071A: IRQ now: %i\n", val);
pci_regs[addr] = val;
case 0x3c: /* PCI_ILR */
pclog("AB0B:071A Device %02X: IRQ now: %i\n", dev->card, val);
dev->pci_regs[addr] = val;
return;
}
}
void
pci_dummy_init(void)
static void
pci_dummy_reset(void *priv)
{
card = pci_add_card(PCI_ADD_NORMAL, pci_dummy_pci_read, pci_dummy_pci_write, NULL);
pci_dummy_t *dev = (pci_dummy_t *) priv;
pci_bar[0].addr_regs[0] = 0x01;
pci_regs[0x04] = 0x03;
/* Lower the IRQ. */
pci_dummy_interrupt(0, dev);
pci_regs[0x3D] = PCI_INTD;
/* Disable I/O and memory accesses. */
pci_dummy_pci_write(0x00, 0x04, 0x00, dev);
/* Zero all the registers. */
memset(dev, 0x00, sizeof(pci_dummy_t));
}
static void
pci_dummy_close(void *priv)
{
pci_dummy_t *dev = (pci_dummy_t *) priv;
free(dev);
}
static void *
pci_dummy_card_init(const device_t *info)
{
pci_dummy_t *dev = (pci_dummy_t *) calloc(1, sizeof(pci_dummy_t));
dev->card = pci_add_card(PCI_ADD_NORMAL, pci_dummy_pci_read, pci_dummy_pci_write, dev);
return dev;
}
const device_t pci_dummy_device = {
.name = "Dummy Device (PCI)",
.internal_name = "pci_dummy",
.flags = DEVICE_PCI,
.local = 0,
.init = pci_dummy_card_init,
.close = pci_dummy_close,
.reset = pci_dummy_reset,
{ .available = NULL },
.speed_changed = NULL,
.force_redraw = NULL,
.config = NULL
};
void
pci_dummy_init(int min_slot, int max_slot, int nb_slot, int sb_slot)
{
int i = 0, j = 1;
for (i = min_slot; i <= max_slot; i++) {
if ((i != nb_slot) && (i != sb_slot)) {
pci_register_slot(i, PCI_CARD_NORMAL, 1, 3, 2, 4);
device_add_inst(&pci_dummy_device, j);
j++;
}
}
}

View File

@@ -221,6 +221,12 @@ if(WIN32 AND NOT MINGW)
target_sources(plat PRIVATE ../win/win_opendir.c)
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)
target_sources(ui PRIVATE macos_event_filter.mm)
if(MOLTENVK)

View File

@@ -27,6 +27,8 @@
#include <QCheckBox>
#include <QFrame>
#include <QLabel>
#include <QDir>
#include <QSettings>
extern "C" {
#include <86box/86box.h>
@@ -40,6 +42,10 @@ extern "C" {
#include "qt_filefield.hpp"
#include "qt_models_common.hpp"
#ifdef Q_OS_LINUX
# include <sys/stat.h>
# include <sys/sysmacros.h>
#endif
DeviceConfig::DeviceConfig(QWidget *parent)
: QDialog(parent)
@@ -53,6 +59,40 @@ DeviceConfig::~DeviceConfig()
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
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);
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;
}
@@ -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));
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:
{
auto *cbox = dc.findChild<QComboBox *>(config->name);

View File

@@ -43,7 +43,7 @@ Q_IMPORT_PLUGIN(QWindowsVistaStylePlugin)
# include "qt_winrawinputfilter.hpp"
# include "qt_winmanagerfilter.hpp"
# include <86box/win.h>
# include <Shobjidl.h>
# include <shobjidl.h>
#endif
extern "C" {

View File

@@ -169,7 +169,7 @@ SettingsMachine::on_comboBoxMachine_currentIndexChanged(int index)
}
int machineId = ui->comboBoxMachine->currentData().toInt();
const auto *device = machine_getdevice(machineId);
const auto *device = machine_get_device(machineId);
ui->pushButtonConfigure->setEnabled((device != nullptr) && (device->config != nullptr));
auto *modelCpu = ui->comboBoxCPU->model();
@@ -304,6 +304,6 @@ SettingsMachine::on_pushButtonConfigure_clicked()
{
// deviceconfig_inst_open
int machineId = ui->comboBoxMachine->currentData().toInt();
const auto *device = machine_getdevice(machineId);
const auto *device = machine_get_device(machineId);
DeviceConfig::ConfigureDevice(device, 0, qobject_cast<Settings *>(Settings::settings));
}

View File

@@ -27,6 +27,7 @@ extern "C" {
#include <86box/machine.h>
#include <86box/lpt.h>
#include <86box/serial.h>
#include <86box/serial_passthrough.h>
}
#include "qt_deviceconfig.hpp"
@@ -66,6 +67,15 @@ SettingsPorts::SettingsPorts(QWidget *parent)
auto *checkBox = findChild<QCheckBox *>(QString("checkBoxSerial%1").arg(i + 1));
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()
@@ -87,6 +97,11 @@ SettingsPorts::save()
auto *checkBox = findChild<QCheckBox *>(QString("checkBoxSerial%1").arg(i + 1));
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
@@ -112,3 +127,51 @@ SettingsPorts::on_checkBoxParallel4_stateChanged(int state)
{
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);
}

View File

@@ -15,6 +15,30 @@ public:
~SettingsPorts();
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:
void on_checkBoxParallel3_stateChanged(int arg1);
void on_checkBoxParallel2_stateChanged(int arg1);

View File

@@ -13,7 +13,7 @@
<property name="windowTitle">
<string>Form</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<layout class="QGridLayout" name="gridLayout_4">
<property name="leftMargin">
<number>0</number>
</property>
@@ -26,7 +26,7 @@
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<item row="0" column="0">
<layout class="QFormLayout" name="formLayout">
<item row="0" column="0">
<widget class="QLabel" name="label">
@@ -70,29 +70,8 @@
</item>
</layout>
</item>
<item>
<item row="1" column="0">
<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">
<widget class="QCheckBox" name="checkBoxSerial2">
<property name="text">
<string>Serial port 2</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QCheckBox" name="checkBoxParallel2">
<property name="text">
@@ -100,13 +79,6 @@
</property>
</widget>
</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">
<widget class="QCheckBox" name="checkBoxParallel3">
<property name="text">
@@ -114,10 +86,17 @@
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QCheckBox" name="checkBoxSerial4">
<item row="2" column="0">
<widget class="QCheckBox" name="checkBoxSerial3">
<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>
</widget>
</item>
@@ -128,20 +107,117 @@
</property>
</widget>
</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>
</item>
<item>
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
<item row="3" column="0">
<layout class="QGridLayout" name="gridLayout_5">
<property name="sizeConstraint">
<enum>QLayout::SetDefaultConstraint</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
<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">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</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>
</widget>

View File

@@ -17,7 +17,7 @@
#include "qt_winmanagerfilter.hpp"
#include <Windows.h>
#include <windows.h>
#include <86box/win.h>
bool

View File

@@ -35,7 +35,7 @@
#include <QMenuBar>
#include <Windows.h>
#include <windows.h>
#include <86box/keyboard.h>
#include <86box/mouse.h>

View File

@@ -37,7 +37,7 @@
#include <QAbstractNativeEventFilter>
#include <QByteArray>
#include <Windows.h>
#include <windows.h>
#include <memory>

View File

@@ -81,9 +81,17 @@ xinput2_get_xtest_pointer()
{
/* The XTEST pointer events injected by VNC servers to move the cursor always report
absolute coordinates, despite XTEST declaring relative axes (related: SDL issue 1836).
This looks for the XTEST pointer so that we can assume it's absolute as a workaround. */
This looks for the XTEST pointer so that we can assume it's absolute as a workaround.
TigerVNC publishes both the XTEST pointer and a TigerVNC pointer, but actual
RawMotion events are published using the TigerVNC pointer */
int devs;
XIDeviceInfo *info = XIQueryDevice(disp, XIAllDevices, &devs), *dev;
for (int i = 0; i < devs; i++) {
dev = &info[i];
if ((dev->use == XISlavePointer) && !strcmp(dev->name, "TigerVNC pointer"))
return dev->deviceid;
}
for (int i = 0; i < devs; i++) {
dev = &info[i];
if ((dev->use == XISlavePointer) && !strcmp(dev->name, "Virtual core XTEST pointer"))

View File

@@ -3519,15 +3519,30 @@ scsi_cdrom_identify(ide_t *ide, int ide_has_dma)
} else if ((!strcmp(cdrom_drive_types[dev->drv->type].internal_name, "SONY_CD-ROM_CDU311_3.0h"))) {
ide_padstr((char *) (ide->buffer + 23), "3.0h ", 8); /* Firmware */
ide_padstr((char *) (ide->buffer + 27), "SONY CD-ROM CDU311 ", 40); /* Model */
} else if ((!strcmp(cdrom_drive_types[dev->drv->type].internal_name, "NEC_CDR-1300A_1.05"))) {
} else if ((!strcmp(cdrom_drive_types[dev->drv->type].internal_name, "NEC_CD-ROM_DRIVE280_1.05"))) {
ide_padstr((char *) (ide->buffer + 23), "1.05 ", 8); /* Firmware */
ide_padstr((char *) (ide->buffer + 27), "NEC CDR-1300A ", 40); /* Model */
ide_padstr((char *) (ide->buffer + 27), "NEC CD-ROM DRIVE:280 ", 40); /* Model */
} else if ((!strcmp(cdrom_drive_types[dev->drv->type].internal_name, "NEC_CD-ROM_DRIVE280_3.08"))) {
ide_padstr((char *) (ide->buffer + 23), "3.08 ", 8); /* Firmware */
ide_padstr((char *) (ide->buffer + 27), "NEC CD-ROM DRIVE:280 ", 40); /* Model */
} else if ((!strcmp(cdrom_drive_types[dev->drv->type].internal_name, "NEC_CD-ROM_DRIVE273_4.20"))) {
ide_padstr((char *) (ide->buffer + 23), "4.20 ", 8); /* Firmware */
ide_padstr((char *) (ide->buffer + 27), "NEC CD-ROM DRIVE:273 ", 40); /* Model */
} else if ((!strcmp(cdrom_drive_types[dev->drv->type].internal_name, "TOSHIBA_CD-ROM_XM-5302TA_0305"))) {
ide_padstr((char *) (ide->buffer + 23), "0305 ", 8); /* Firmware */
ide_padstr((char *) (ide->buffer + 27), "TOSHIBA CD-ROM XM-5302TA ", 40); /* Model */
} else if ((!strcmp(cdrom_drive_types[dev->drv->type].internal_name, "TOSHIBA_CD-ROM_XM-5702B_TA70"))) {
ide_padstr((char *) (ide->buffer + 23), "TA70 ", 8); /* Firmware */
ide_padstr((char *) (ide->buffer + 27), "TOSHIBA CD-ROM XM-5702B ", 40); /* Model */
} else if ((!strcmp(cdrom_drive_types[dev->drv->type].internal_name, "GOLDSTAR_CRD-8160B_3.14"))) {
ide_padstr((char *) (ide->buffer + 23), "3.14 ", 8); /* Firmware */
ide_padstr((char *) (ide->buffer + 27), "GOLDSTAR CRD-8160B ", 40); /* Model */
} else if ((!strcmp(cdrom_drive_types[dev->drv->type].internal_name, "MATSHITA_CR-571_1.0e"))) {
ide_padstr((char *) (ide->buffer + 23), "1.0e ", 8); /* Firmware */
ide_padstr((char *) (ide->buffer + 27), "MATSHITA CR-571 ", 40); /* Model */
} else if ((!strcmp(cdrom_drive_types[dev->drv->type].internal_name, "MATSHITA_CR-572_1.0j"))) {
ide_padstr((char *) (ide->buffer + 23), "1.0j ", 8); /* Firmware */
ide_padstr((char *) (ide->buffer + 27), "MATSHITA CR-572 ", 40); /* Model */
} else if ((!strcmp(cdrom_drive_types[dev->drv->type].internal_name, "MATSHITA_CD-ROM_CR-587_7S13"))) {
ide_padstr((char *) (ide->buffer + 23), "7S13 ", 8); /* Firmware */
ide_padstr((char *) (ide->buffer + 27), "MATSHITA CD-ROM CR-587 ", 40); /* Model */

View File

@@ -13,9 +13,11 @@
#
# Copyright 2021 Cacodemon345.
# 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)
target_sources(plat PRIVATE unix_thread.c)

View 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;
}

View File

@@ -10,13 +10,14 @@
#
# 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)
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
win_settings.c win_devconf.c win_snd_gain.c win_specify_dim.c win_new_floppy.c

View File

@@ -76,6 +76,9 @@ ifeq ($(DEV_BUILD), y)
ifndef PAS16
PAS16 := y
endif
ifndef PCI_DUMMY
PCI_DUMMY := y
endif
ifndef SIO_DETECT
SIO_DETECT := y
endif
@@ -137,6 +140,9 @@ else
ifndef PAS16
PAS16 := n
endif
ifndef PCI_DUMMY
PCI_DUMMY := n
endif
ifndef SIO_DETECT
SIO_DETECT := n
endif
@@ -476,6 +482,11 @@ ifeq ($(DEV_BRANCH), y)
DEVBROBJ += snd_pas16.o
endif
ifeq ($(PCI_DUMMY), y)
OPTS += -DUSE_PCI_DUMMY
DEVBROBJ += pci_dummy.o
endif
ifeq ($(SIO_DETECT), y)
OPTS += -DUSE_SIO_DETECT
DEVBROBJ += sio_detect.o
@@ -586,7 +597,7 @@ DEVOBJ := bugger.o cartridge.o cassette.o hasp.o hwm.o hwm_lm75.o hwm_lm78.o hwm
mouse_bus.o \
mouse_serial.o mouse_ps2.o \
mouse_wacom_tablet.o \
phoenix_486_jumper.o
phoenix_486_jumper.o serial_passthrough.o
SIOOBJ := sio_acc3221.o sio_ali5123.o \
sio_f82c710.o sio_82091aa.o sio_fdc37c6xx.o \
@@ -739,7 +750,7 @@ VOODOOOBJ := vid_voodoo.o vid_voodoo_banshee.o \
PLATOBJ := win.o \
win_dynld.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 \
win_sdl.o win_opengl.o win_opengl_glslp.o glad.o \
@@ -772,13 +783,19 @@ ifdef EXOBJ
OBJ += $(EXOBJ)
endif
ifeq ($(LOG), y)
MWIN := -lcomdlg32
else
MWIN := -mwindows
endif
ifeq ($(OPENAL), y)
LIBS := -mwindows -lopenal -lcomctl32 -lSDL2 -limagehlp -ldinput8 -ldxguid -ldxerr8 -luser32 -lgdi32 -lwinmm -limm32 -lole32 -loleaut32 -lshell32 -lversion -luuid -lws2_32
LIBS := $(MWIN) -lopenal -lcomctl32 -lSDL2 -limagehlp -ldinput8 -ldxguid -ldxerr8 -luser32 -lgdi32 -lwinmm -limm32 -lole32 -loleaut32 -lshell32 -lversion -luuid -lws2_32
else
ifeq ($(FAUDIO), y)
LIBS := -mwindows -lfaudio -lcomctl32 -lSDL2 -limagehlp -ldinput8 -ldxguid -ldxerr8 -luser32 -lgdi32 -lwinmm -limm32 -lole32 -loleaut32 -lshell32 -lversion -luuid -lws2_32
LIBS := $(MWIN) -lfaudio -lcomctl32 -lSDL2 -limagehlp -ldinput8 -ldxguid -ldxerr8 -luser32 -lgdi32 -lwinmm -limm32 -lole32 -loleaut32 -lshell32 -lversion -luuid -lws2_32
else
LIBS := -mwindows -lcomctl32 -lSDL2 -limagehlp -ldinput8 -ldxguid -ldxerr8 -luser32 -lgdi32 -lwinmm -limm32 -lole32 -loleaut32 -lshell32 -lversion -luuid -lws2_32
LIBS := $(MWIN) -lcomctl32 -lSDL2 -limagehlp -ldinput8 -ldxguid -ldxerr8 -luser32 -lgdi32 -lwinmm -limm32 -lole32 -loleaut32 -lshell32 -lversion -luuid -lws2_32
endif
endif

View File

@@ -328,6 +328,10 @@ END
#define STR_PARALLEL2 "Povolit port LPT2"
#define STR_PARALLEL3 "Povolit port LPT3"
#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_FDC "Disketový řadič:"

View File

@@ -328,6 +328,10 @@ END
#define STR_PARALLEL2 "Parallelport 2"
#define STR_PARALLEL3 "Parallelport 3"
#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_FDC "FD-Controller:"

View File

@@ -453,54 +453,78 @@ BEGIN
CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
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,
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
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,
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
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,
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
CONTROL STR_SERIAL1, IDC_CHECK_SERIAL1,
"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,
"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,
"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,
"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,
"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,
"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,
"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,
"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
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_PARALLEL3
#undef STR_PARALLEL4
#undef STR_SERIAL_PASS1
#undef STR_SERIAL_PASS2
#undef STR_SERIAL_PASS3
#undef STR_SERIAL_PASS4
#undef STR_HDC
#undef STR_FDC

View File

@@ -328,6 +328,10 @@ END
#define STR_PARALLEL2 "Parallel port 2"
#define STR_PARALLEL3 "Parallel port 3"
#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_FDC "FD Controller:"

View File

@@ -328,6 +328,10 @@ END
#define STR_PARALLEL2 "Parallel port 2"
#define STR_PARALLEL3 "Parallel port 3"
#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_FDC "FD Controller:"

View File

@@ -328,6 +328,10 @@ END
#define STR_PARALLEL2 "Puerto paralelo 2"
#define STR_PARALLEL3 "Puerto paralelo 3"
#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_FDC "Controladora FD:"

View File

@@ -328,6 +328,10 @@ END
#define STR_PARALLEL2 "Rinnakkaisportti 2"
#define STR_PARALLEL3 "Rinnakkaisportti 3"
#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_FDC "Levykeohjain:"

View File

@@ -328,6 +328,10 @@ END
#define STR_PARALLEL2 "Port parallèle 2"
#define STR_PARALLEL3 "Port parallèle 3"
#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_FDC "Contrôleur FD:"

View File

@@ -328,6 +328,10 @@ END
#define STR_PARALLEL2 "Paralelna vrata 2"
#define STR_PARALLEL3 "Paralelna vrata 3"
#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_FDC "Kontroler diskete:"

View File

@@ -333,6 +333,10 @@ END
#define STR_PARALLEL2 "Párhuzamos port 2"
#define STR_PARALLEL3 "Párhuzamos port 3"
#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_FDC "Floppy-vezérlő:"

View File

@@ -329,6 +329,10 @@ END
#define STR_PARALLEL2 "Porta parallela 2"
#define STR_PARALLEL3 "Porta parallela 3"
#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_FDC "Controller FD:"

View File

@@ -328,6 +328,10 @@ END
#define STR_PARALLEL2 "パラレルポート2"
#define STR_PARALLEL3 "パラレルポート3"
#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_FDC "FDコントローラー:"

View File

@@ -328,6 +328,10 @@ END
#define STR_PARALLEL2 "병렬 포트 2"
#define STR_PARALLEL3 "병렬 포트 3"
#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_FDC "FD 컨트롤러:"

View File

@@ -328,6 +328,10 @@ END
#define STR_PARALLEL2 "Port równoległy 2"
#define STR_PARALLEL3 "Port równoległy 3"
#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_FDC "Kontroler dyskietek:"

View File

@@ -331,6 +331,10 @@ END
#define STR_PARALLEL2 "Porta paralela 2"
#define STR_PARALLEL3 "Porta paralela 3"
#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_FDC "Controlador FD:"

View File

@@ -328,6 +328,10 @@ END
#define STR_PARALLEL2 "Porta paralela 2"
#define STR_PARALLEL3 "Porta paralela 3"
#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_FDC "Controlador FD:"

View File

@@ -328,6 +328,10 @@ END
#define STR_PARALLEL2 "Параллельный порт LPT2"
#define STR_PARALLEL3 "Параллельный порт LPT3"
#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_FDC "Контроллер FD:"

View File

@@ -328,6 +328,10 @@ END
#define STR_PARALLEL2 "Paralelna vrata 2"
#define STR_PARALLEL3 "Paralelna vrata 3"
#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_FDC "Krmilnik disketnika:"

View File

@@ -328,6 +328,10 @@ END
#define STR_PARALLEL2 "Paralel port 2"
#define STR_PARALLEL3 "Paralel port 3"
#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_FDC "FD Kontrolcüsü:"

View File

@@ -328,6 +328,10 @@ END
#define STR_PARALLEL2 "Паралельний порт LPT2"
#define STR_PARALLEL3 "Паралельний порт LPT3"
#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_FDC "Контролер FD:"

View File

@@ -328,6 +328,10 @@ END
#define STR_PARALLEL2 "并口 2"
#define STR_PARALLEL3 "并口 3"
#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_FDC "软盘控制器:"

View File

@@ -328,6 +328,10 @@ END
#define STR_PARALLEL2 "並列埠 2"
#define STR_PARALLEL3 "並列埠 3"
#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_FDC "軟碟控制器:"

View File

@@ -36,7 +36,7 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#define UNICODE
#include <Windows.h>
#include <windows.h>
#include <process.h>
#include <SDL2/SDL.h>
#include <SDL2/SDL_syswm.h>

View 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;
}

View File

@@ -71,6 +71,7 @@
#include <86box/plat.h>
#include <86box/ui.h>
#include <86box/win.h>
#include <86box/serial_passthrough.h>
#include "../disk/minivhd/minivhd.h"
#include "../disk/minivhd/minivhd_util.h"
@@ -111,6 +112,7 @@ static char temp_pcap_dev[NET_CARD_MAX][128];
/* Ports category */
static int temp_lpt_devices[PARALLEL_MAX];
static int temp_serial[SERIAL_MAX], temp_lpt[PARALLEL_MAX];
static int temp_serial_passthrough_enabled[SERIAL_MAX];
/* Other peripherals category */
static int temp_fdc_card, temp_hdc, temp_ide_ter, temp_ide_qua, temp_cassette;
@@ -358,11 +360,13 @@ win_settings_init(void)
/* Ports category */
for (i = 0; i < PARALLEL_MAX; i++) {
temp_lpt_devices[i] = lpt_ports[i].device;
temp_lpt[i] = lpt_ports[i].enabled;
temp_lpt_devices[i] = lpt_ports[i].device;
temp_lpt[i] = lpt_ports[i].enabled;
}
for (i = 0; i < SERIAL_MAX; i++) {
temp_serial[i] = com_ports[i].enabled;
temp_serial_passthrough_enabled[i] = serial_passthrough_enabled[i];
}
for (i = 0; i < SERIAL_MAX; i++)
temp_serial[i] = com_ports[i].enabled;
/* Storage devices category */
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[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_passthrough_enabled[i] != serial_passthrough_enabled[i]);
}
/* Storage devices category */
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].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];
serial_passthrough_enabled[i] = temp_serial_passthrough_enabled[i];
}
/* Storage devices category */
for (i = 0; i < SCSI_BUS_MAX; i++)
@@ -755,7 +763,7 @@ win_settings_machine_recalc_machine(HWND hdlg)
lptsTemp = (LPTSTR) malloc(512 * sizeof(WCHAR));
d = (device_t *) machine_getdevice(temp_machine);
d = (device_t *) machine_get_device(temp_machine);
settings_enable_window(hdlg, IDC_CONFIGURE_MACHINE, d && d->config);
settings_reset_content(hdlg, IDC_COMBO_CPU_TYPE);
@@ -987,7 +995,7 @@ win_settings_machine_proc(HWND hdlg, UINT message, WPARAM wParam, LPARAM lParam)
break;
case IDC_CONFIGURE_MACHINE:
temp_machine = listtomachine[settings_get_cur_sel(hdlg, IDC_COMBO_MACHINE)];
temp_deviceconfig |= deviceconfig_open(hdlg, (void *) machine_getdevice(temp_machine));
temp_deviceconfig |= deviceconfig_open(hdlg, (void *) machine_get_device(temp_machine));
break;
}
@@ -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]);
}
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_SERIAL_PASS1 + i, temp_serial_passthrough_enabled[i]);
}
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);
}
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_passthrough_enabled[i] = settings_get_check(hdlg, IDC_CHECK_SERIAL_PASS1 + i);
}
default:
return FALSE;

View File

@@ -2,8 +2,8 @@
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <Windows.h>
#include <CommCtrl.h>
#include <windows.h>
#include <commctrl.h>
#include <86box/86box.h>
#include <86box/plat.h>
#include <86box/resource.h>