Add beta2 patch: nullmodem and serial update. Add some more configure tests for OS/2 and Mac OS X
Imported-from: https://svn.code.sf.net/p/dosbox/code-0/dosbox/trunk@2758
This commit is contained in:
parent
46d89dc3b3
commit
85af8429ac
24 changed files with 3195 additions and 1536 deletions
|
@ -4,5 +4,7 @@ noinst_LIBRARIES = libserial.a
|
|||
|
||||
libserial_a_SOURCES = directserial_win32.cpp directserial_win32.h \
|
||||
serialdummy.cpp serialdummy.h serialport.cpp \
|
||||
softmodem.cpp softmodem.h \
|
||||
directserial_os2.h directserial_os2.cpp
|
||||
softmodem.cpp softmodem.h misc_util.cpp misc_util.h \
|
||||
directserial_os2.h directserial_os2.cpp \
|
||||
directserial_posix.h directserial_posix.cpp \
|
||||
nullmodem.cpp nullmodem.h
|
||||
|
|
361
src/hardware/serialport/directserial_posix.cpp
Normal file
361
src/hardware/serialport/directserial_posix.cpp
Normal file
|
@ -0,0 +1,361 @@
|
|||
/*
|
||||
* Copyright (C) 2002-2007 The DOSBox Team
|
||||
*
|
||||
* 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
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
/* $Id: directserial_posix.cpp,v 1.1 2007-01-13 08:35:49 qbix79 Exp $ */
|
||||
|
||||
#include "dosbox.h"
|
||||
|
||||
#if C_DIRECTSERIAL
|
||||
|
||||
// Posix version
|
||||
#if defined (LINUX)
|
||||
|
||||
#include "serialport.h"
|
||||
#include "directserial_posix.h"
|
||||
#include "pic.h"
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/ioctl.h>
|
||||
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
/* This is a serial passthrough class. Its amazingly simple to */
|
||||
/* write now that the serial ports themselves were abstracted out */
|
||||
|
||||
CDirectSerial::CDirectSerial (Bitu id, CommandLine* cmd)
|
||||
:CSerial (id, cmd) {
|
||||
InstallationSuccessful = false;
|
||||
|
||||
rx_retry = 0;
|
||||
rx_retry_max = 0;
|
||||
|
||||
std::string prefix="/dev/";
|
||||
std::string tmpstring;
|
||||
if(!cmd->FindStringBegin("realport:",tmpstring,false)) return;
|
||||
|
||||
#if SERIAL_DEBUG
|
||||
if(dbg_modemcontrol)
|
||||
fprintf(debugfp,"%12.3f Port type directserial realport %s\r\n",
|
||||
PIC_FullIndex(),tmpstring.c_str());
|
||||
#endif
|
||||
|
||||
prefix.append(tmpstring);
|
||||
|
||||
// rxdelay: How many milliseconds to wait before causing an
|
||||
// overflow when the application is unresponsive.
|
||||
if(getBituSubstring("rxdelay:", &rx_retry_max, cmd)) {
|
||||
if(!(rx_retry_max<=10000)) rx_retry_max=0;
|
||||
}
|
||||
|
||||
const char* tmpchar=prefix.c_str();
|
||||
|
||||
LOG_MSG ("Serial%d: Opening %s", COMNUMBER, tmpchar);
|
||||
|
||||
fileHandle = open (tmpchar, O_RDWR | O_NOCTTY | O_NONBLOCK);
|
||||
|
||||
if (fileHandle < 0) {
|
||||
LOG_MSG ("Serial%d: Serial Port \"%s\" could not be opened.",
|
||||
COMNUMBER, tmpchar);
|
||||
if (errno == 2) {
|
||||
LOG_MSG ("The specified port does not exist.");
|
||||
} else if (errno == EBUSY) {
|
||||
LOG_MSG ("The specified port is already in use.");
|
||||
} else {
|
||||
LOG_MSG ("Errno %d occurred.", errno);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
int result = tcgetattr(fileHandle, &termInfo);
|
||||
|
||||
|
||||
if (result==-1) {
|
||||
// Handle the error.
|
||||
LOG_MSG ("tcgetattr failed with error %d.\n", errno);
|
||||
return;
|
||||
}
|
||||
|
||||
// save it here to restore in destructor
|
||||
tcgetattr(fileHandle,&backup);
|
||||
|
||||
// initialize the port
|
||||
termInfo.c_cflag = CS8 | CREAD | CLOCAL; // noparity, 1 stopbit
|
||||
termInfo.c_iflag = PARMRK | INPCK;
|
||||
termInfo.c_oflag = 0;
|
||||
termInfo.c_lflag = 0;
|
||||
|
||||
cfsetospeed (&termInfo, B9600);
|
||||
cfsetispeed (&termInfo, B9600);
|
||||
|
||||
termInfo.c_cc[VMIN] = 0;
|
||||
termInfo.c_cc[VTIME] = 0;
|
||||
|
||||
tcflush (fileHandle, TCIFLUSH);
|
||||
tcsetattr (fileHandle, TCSANOW, &termInfo);
|
||||
|
||||
//initialise base class
|
||||
CSerial::Init_Registers();
|
||||
InstallationSuccessful = true;
|
||||
receiveblock=false;
|
||||
|
||||
setEvent(SERIAL_POLLING_EVENT, 1); // millisecond tick
|
||||
}
|
||||
|
||||
CDirectSerial::~CDirectSerial () {
|
||||
if (fileHandle >= 0)
|
||||
{
|
||||
tcsetattr(fileHandle, TCSANOW, &backup);
|
||||
close(fileHandle);
|
||||
}
|
||||
// We do not use own events so we don't have to clear them.
|
||||
}
|
||||
|
||||
void CDirectSerial::handleUpperEvent(Bit16u type) {
|
||||
|
||||
switch(type) {
|
||||
case SERIAL_POLLING_EVENT: {
|
||||
setEvent(SERIAL_POLLING_EVENT, 1);
|
||||
if(!receiveblock) {
|
||||
if(((!(LSR&LSR_RX_DATA_READY_MASK)) || rx_retry>=rx_retry_max ))
|
||||
{
|
||||
ReadCharacter();
|
||||
} else rx_retry++;
|
||||
}
|
||||
// check for errors
|
||||
CheckErrors();
|
||||
// update Modem input line states
|
||||
updateMSR ();
|
||||
break;
|
||||
}
|
||||
case 40: {
|
||||
// receive time is up
|
||||
receiveblock=false;
|
||||
// check if there is something to receive
|
||||
if(((!(LSR&LSR_RX_DATA_READY_MASK)) || rx_retry>=rx_retry_max ))
|
||||
{
|
||||
ReadCharacter();
|
||||
} else rx_retry++;
|
||||
break;
|
||||
}
|
||||
case SERIAL_TX_EVENT: {
|
||||
if(!receiveblock) {
|
||||
if(((!(LSR&LSR_RX_DATA_READY_MASK)) || rx_retry>=rx_retry_max ))
|
||||
{
|
||||
ReadCharacter();
|
||||
} else rx_retry++;
|
||||
}
|
||||
ByteTransmitted();
|
||||
break;
|
||||
}
|
||||
case SERIAL_THR_EVENT: {
|
||||
ByteTransmitting();
|
||||
setEvent(SERIAL_TX_EVENT,bytetime+0.03f);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CDirectSerial::ReadCharacter()
|
||||
{
|
||||
Bit8u chRead = 0;
|
||||
int dwRead = 0;
|
||||
rx_retry=0;
|
||||
|
||||
dwRead=read(fileHandle,&chRead,1);
|
||||
if (dwRead==1) {
|
||||
if(chRead==0xff) // error escape
|
||||
{
|
||||
dwRead=read(fileHandle,&chRead,1);
|
||||
if(chRead==0x00) // an error
|
||||
{
|
||||
dwRead=read(fileHandle,&chRead,1);
|
||||
if(chRead==0x0)receiveError(LSR_RX_BREAK_MASK);
|
||||
else receiveError(LSR_PARITY_ERROR_MASK);
|
||||
}
|
||||
}
|
||||
receiveByte (chRead);
|
||||
setEvent(40, bytetime-0.03f); // receive timing
|
||||
receiveblock=true;
|
||||
}
|
||||
}
|
||||
|
||||
void CDirectSerial::CheckErrors() {
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/* updatePortConfig is called when emulated app changes the serial port **/
|
||||
/* parameters baudrate, stopbits, number of databits, parity. **/
|
||||
/*****************************************************************************/
|
||||
void CDirectSerial::updatePortConfig (Bit16u divider, Bit8u lcr) {
|
||||
Bit8u parity = 0;
|
||||
Bit8u bytelength = 0;
|
||||
int baudrate=0;
|
||||
|
||||
// baud
|
||||
termInfo.c_cflag = CREAD | CLOCAL;
|
||||
|
||||
if (divider == 0x1) baudrate = B115200;
|
||||
else if (divider == 0x2) baudrate = B57600;
|
||||
else if (divider == 0x3) baudrate = B38400;
|
||||
else if (divider == 0x6) baudrate = B19200;
|
||||
else if (divider == 0xc) baudrate = B9600;
|
||||
else if (divider == 0x18) baudrate = B4800;
|
||||
else if (divider == 0x30) baudrate = B2400;
|
||||
else if (divider == 0x60) baudrate = B1200;
|
||||
else if (divider == 0xc0) baudrate = B600;
|
||||
else if (divider == 0x180) baudrate = B300;
|
||||
else if (divider == 0x417) baudrate = B110;
|
||||
|
||||
// Don't think termios supports nonstandard baudrates
|
||||
else baudrate = B9600;
|
||||
|
||||
// byte length
|
||||
bytelength = lcr & 0x3;
|
||||
bytelength += 5;
|
||||
|
||||
switch (bytelength) {
|
||||
case 5:
|
||||
termInfo.c_cflag |= CS5;
|
||||
break;
|
||||
|
||||
case 6:
|
||||
termInfo.c_cflag |= CS6;
|
||||
break;
|
||||
|
||||
case 7:
|
||||
termInfo.c_cflag |= CS7;
|
||||
break;
|
||||
|
||||
case 8:
|
||||
default:
|
||||
termInfo.c_cflag |= CS8;
|
||||
break;
|
||||
}
|
||||
|
||||
// parity
|
||||
parity = lcr & 0x38;
|
||||
parity >>= 3;
|
||||
switch (parity) {
|
||||
case 0x1:
|
||||
termInfo.c_cflag |= PARODD;
|
||||
termInfo.c_cflag |= PARENB;
|
||||
break;
|
||||
case 0x3:
|
||||
termInfo.c_cflag |= PARENB;
|
||||
break;
|
||||
case 0x5:
|
||||
|
||||
// "works on many systems"
|
||||
#define CMSPAR 010000000000
|
||||
|
||||
termInfo.c_cflag |= PARODD;
|
||||
termInfo.c_cflag |= PARENB;
|
||||
termInfo.c_cflag |= CMSPAR;
|
||||
//LOG_MSG("Serial%d: Mark parity not supported.", COMNUMBER);
|
||||
break;
|
||||
case 0x7:
|
||||
termInfo.c_cflag |= PARENB;
|
||||
termInfo.c_cflag |= CMSPAR;
|
||||
//LOG_MSG("Serial%d: Space parity not supported.", COMNUMBER);
|
||||
break;
|
||||
default: // no parity
|
||||
break;
|
||||
}
|
||||
|
||||
// stopbits
|
||||
if (lcr & 0x4) termInfo.c_cflag |= CSTOPB;
|
||||
|
||||
cfsetospeed (&termInfo, baudrate);
|
||||
cfsetispeed (&termInfo, baudrate);
|
||||
|
||||
int retval = tcsetattr(fileHandle, TCSANOW, &termInfo);
|
||||
|
||||
if(retval==-1)
|
||||
LOG_MSG ("Serial%d: Desired serial mode not supported", COMNUMBER);
|
||||
|
||||
}
|
||||
|
||||
void CDirectSerial::updateMSR () {
|
||||
long flags = 0;
|
||||
ioctl (fileHandle, TIOCMGET, &flags);
|
||||
|
||||
if (flags & TIOCM_CTS) setCTS(true);
|
||||
else setCTS(false);
|
||||
|
||||
if (flags & TIOCM_DSR) setDSR(true);
|
||||
else setDSR(false);
|
||||
|
||||
if (flags & TIOCM_RI) setRI(true);
|
||||
else setRI(false);
|
||||
|
||||
if (flags & TIOCM_CD) setCD(true);
|
||||
else setCD(false);
|
||||
}
|
||||
|
||||
void CDirectSerial::transmitByte (Bit8u val, bool first) {
|
||||
if((LCR&LCR_BREAK_MASK) == 0) {
|
||||
|
||||
int bytesWritten = write(fileHandle, &val, 1);
|
||||
if (bytesWritten != 1)
|
||||
LOG_MSG ("Serial%d: COM port error: write failed!", idnumber);
|
||||
}
|
||||
if(first) setEvent(SERIAL_THR_EVENT, bytetime/8);
|
||||
else setEvent(SERIAL_TX_EVENT, bytetime);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/* setBreak(val) switches break on or off **/
|
||||
/*****************************************************************************/
|
||||
void CDirectSerial::setBreak (bool value) {
|
||||
if (value) ioctl (fileHandle, TIOCSBRK);
|
||||
else ioctl (fileHandle, TIOCCBRK);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/* updateModemControlLines(mcr) sets DTR and RTS. **/
|
||||
/*****************************************************************************/
|
||||
void CDirectSerial::setRTSDTR(bool rts, bool dtr) {
|
||||
|
||||
long setflags = 0;
|
||||
long clearflags = 0;
|
||||
|
||||
if(rts) setflags |= TIOCM_RTS;
|
||||
else clearflags |= TIOCM_RTS;
|
||||
|
||||
if(dtr) setflags |= TIOCM_DTR;
|
||||
else clearflags |= TIOCM_DTR;
|
||||
|
||||
if(setflags) ioctl (fileHandle, TIOCMBIS, &setflags);
|
||||
if(clearflags) ioctl (fileHandle, TIOCMBIC, &clearflags);
|
||||
}
|
||||
void CDirectSerial::setRTS(bool val) {
|
||||
long flag = TIOCM_RTS;
|
||||
if(val) ioctl(fileHandle, TIOCMBIS, &flag);
|
||||
else ioctl(fileHandle, TIOCMBIC, &flag);
|
||||
}
|
||||
void CDirectSerial::setDTR(bool val) {
|
||||
long flag = TIOCM_DTR;
|
||||
if(val) ioctl(fileHandle, TIOCMBIS, &flag);
|
||||
else ioctl(fileHandle, TIOCMBIC, &flag);
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif
|
69
src/hardware/serialport/directserial_posix.h
Normal file
69
src/hardware/serialport/directserial_posix.h
Normal file
|
@ -0,0 +1,69 @@
|
|||
/*
|
||||
* Copyright (C) 2002-2007 The DOSBox Team
|
||||
*
|
||||
* 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
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
/* $Id: directserial_posix.h,v 1.1 2007-01-13 08:35:49 qbix79 Exp $ */
|
||||
|
||||
// include guard
|
||||
#ifndef DOSBOX_DIRECTSERIAL_POSIX_H
|
||||
#define DOSBOX_DIRECTSERIAL_POSIX_H
|
||||
|
||||
#include "dosbox.h"
|
||||
|
||||
#if C_DIRECTSERIAL
|
||||
#ifdef LINUX
|
||||
|
||||
|
||||
|
||||
#define DIRECTSERIAL_AVAILIBLE
|
||||
#include "serialport.h"
|
||||
#include <termios.h>
|
||||
#include <unistd.h>
|
||||
|
||||
class CDirectSerial : public CSerial {
|
||||
public:
|
||||
termios termInfo;
|
||||
termios backup;
|
||||
int fileHandle;
|
||||
|
||||
CDirectSerial(Bitu id, CommandLine* cmd);
|
||||
~CDirectSerial();
|
||||
bool receiveblock; // It's not a block of data it rather blocks
|
||||
|
||||
Bitu rx_retry; // counter of retries
|
||||
|
||||
Bitu rx_retry_max; // how many POLL_EVENTS to wait before causing
|
||||
// a overrun error.
|
||||
|
||||
void ReadCharacter();
|
||||
void CheckErrors();
|
||||
|
||||
void updatePortConfig(Bit16u divider, Bit8u lcr);
|
||||
void updateMSR();
|
||||
void transmitByte(Bit8u val, bool first);
|
||||
void setBreak(bool value);
|
||||
|
||||
void setRTSDTR(bool rts, bool dtr);
|
||||
void setRTS(bool val);
|
||||
void setDTR(bool val);
|
||||
void handleUpperEvent(Bit16u type);
|
||||
|
||||
};
|
||||
|
||||
#endif // WIN32
|
||||
#endif // C_DIRECTSERIAL
|
||||
#endif // include guard
|
|
@ -16,7 +16,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
/* $Id: directserial_win32.cpp,v 1.4 2007-01-08 19:45:41 qbix79 Exp $ */
|
||||
/* $Id: directserial_win32.cpp,v 1.5 2007-01-13 08:35:49 qbix79 Exp $ */
|
||||
|
||||
#include "dosbox.h"
|
||||
|
||||
|
@ -27,6 +27,8 @@
|
|||
|
||||
#include "serialport.h"
|
||||
#include "directserial_win32.h"
|
||||
#include "misc_util.h"
|
||||
#include "pic.h"
|
||||
|
||||
// Win32 related headers
|
||||
#include <windows.h>
|
||||
|
@ -34,17 +36,41 @@
|
|||
/* This is a serial passthrough class. Its amazingly simple to */
|
||||
/* write now that the serial ports themselves were abstracted out */
|
||||
|
||||
CDirectSerial::CDirectSerial (IO_ReadHandler * rh, IO_WriteHandler * wh,
|
||||
TIMER_TickHandler th, Bit16u baseAddr, Bit8u initIrq,
|
||||
Bit32u initBps, Bit8u bytesize, const char *parity,
|
||||
Bit8u stopbits,const char *realPort)
|
||||
:CSerial (rh, wh, th,baseAddr,initIrq, initBps,
|
||||
bytesize, parity,stopbits) {
|
||||
CDirectSerial::CDirectSerial (Bitu id, CommandLine* cmd)
|
||||
:CSerial (id, cmd) {
|
||||
InstallationSuccessful = false;
|
||||
InstallTimerHandler(th);
|
||||
lastChance = 0;
|
||||
LOG_MSG ("Serial port at %x: Opening %s", base, realPort);
|
||||
hCom = CreateFile (realPort, GENERIC_READ | GENERIC_WRITE, 0, // must be opened with exclusive-access
|
||||
|
||||
rx_retry = 0;
|
||||
rx_retry_max = 0;
|
||||
|
||||
// open the port in NT object space (recommended by Microsoft)
|
||||
// allows the user to open COM10+ and custom port names.
|
||||
std::string prefix="\\\\.\\";
|
||||
std::string tmpstring;
|
||||
if(!cmd->FindStringBegin("realport:",tmpstring,false)) return;
|
||||
|
||||
#if SERIAL_DEBUG
|
||||
if(dbg_modemcontrol)
|
||||
fprintf(debugfp,"%12.3f Port type directserial realport %s\r\n",
|
||||
PIC_FullIndex(),tmpstring.c_str());
|
||||
#endif
|
||||
|
||||
prefix.append(tmpstring);
|
||||
|
||||
// rxdelay: How many milliseconds to wait before causing an
|
||||
// overflow when the application is unresponsive.
|
||||
if(getBituSubstring("rxdelay:", &rx_retry_max, cmd)) {
|
||||
if(!(rx_retry_max<=10000)) {
|
||||
rx_retry_max=0;
|
||||
}
|
||||
}
|
||||
|
||||
const char* tmpchar=prefix.c_str();
|
||||
|
||||
LOG_MSG ("Serial%d: Opening %s", COMNUMBER, tmpstring.c_str());
|
||||
hCom = CreateFile (tmpchar,
|
||||
GENERIC_READ | GENERIC_WRITE, 0,
|
||||
// must be opened with exclusive-access
|
||||
NULL, // no security attributes
|
||||
OPEN_EXISTING, // must use OPEN_EXISTING
|
||||
0, // non overlapped I/O
|
||||
|
@ -53,7 +79,8 @@ CDirectSerial::CDirectSerial (IO_ReadHandler * rh, IO_WriteHandler * wh,
|
|||
|
||||
if (hCom == INVALID_HANDLE_VALUE) {
|
||||
int error = GetLastError ();
|
||||
LOG_MSG ("Serial port \"%s\" could not be opened.", realPort);
|
||||
LOG_MSG ("Serial%d: Serial Port \"%s\" could not be opened.",
|
||||
COMNUMBER, tmpstring.c_str());
|
||||
if (error == 2) {
|
||||
LOG_MSG ("The specified port does not exist.");
|
||||
} else if (error == 5) {
|
||||
|
@ -61,19 +88,48 @@ CDirectSerial::CDirectSerial (IO_ReadHandler * rh, IO_WriteHandler * wh,
|
|||
} else {
|
||||
LOG_MSG ("Windows error %d occurred.", error);
|
||||
}
|
||||
|
||||
hCom = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
dcb.DCBlength=sizeof(dcb);
|
||||
fSuccess = GetCommState (hCom, &dcb);
|
||||
|
||||
if (!fSuccess) {
|
||||
// Handle the error.
|
||||
LOG_MSG ("GetCommState failed with error %d.\n", GetLastError ());
|
||||
hCom = 0;
|
||||
hCom = INVALID_HANDLE_VALUE;
|
||||
return;
|
||||
}
|
||||
|
||||
// initialize the port
|
||||
dcb.BaudRate=CBR_9600;
|
||||
dcb.fBinary=true;
|
||||
dcb.fParity=true;
|
||||
dcb.fOutxCtsFlow=false;
|
||||
dcb.fOutxDsrFlow=false;
|
||||
dcb.fDtrControl=DTR_CONTROL_DISABLE;
|
||||
dcb.fDsrSensitivity=false;
|
||||
|
||||
dcb.fOutX=false;
|
||||
dcb.fInX=false;
|
||||
dcb.fErrorChar=0;
|
||||
dcb.fNull=false;
|
||||
dcb.fRtsControl=RTS_CONTROL_DISABLE;
|
||||
dcb.fAbortOnError=false;
|
||||
|
||||
dcb.ByteSize=8;
|
||||
dcb.Parity=NOPARITY;
|
||||
dcb.StopBits=ONESTOPBIT;
|
||||
|
||||
fSuccess = SetCommState (hCom, &dcb);
|
||||
|
||||
if (!fSuccess) {
|
||||
// Handle the error.
|
||||
LOG_MSG ("SetCommState failed with error %d.\n", GetLastError ());
|
||||
hCom = INVALID_HANDLE_VALUE;
|
||||
return;
|
||||
}
|
||||
|
||||
// Configure timeouts to effectively use polling
|
||||
COMMTIMEOUTS ct;
|
||||
ct.ReadIntervalTimeout = MAXDWORD;
|
||||
|
@ -83,50 +139,103 @@ CDirectSerial::CDirectSerial (IO_ReadHandler * rh, IO_WriteHandler * wh,
|
|||
ct.WriteTotalTimeoutMultiplier = 0;
|
||||
SetCommTimeouts (hCom, &ct);
|
||||
|
||||
CSerial::Init_Registers (initBps, bytesize, parity, stopbits);
|
||||
CSerial::Init_Registers();
|
||||
InstallationSuccessful = true;
|
||||
//LOG_MSG("InstSuccess");
|
||||
receiveblock=false;
|
||||
|
||||
ClearCommBreak (hCom);
|
||||
setEvent(SERIAL_POLLING_EVENT, 1); // millisecond tick
|
||||
}
|
||||
|
||||
CDirectSerial::~CDirectSerial () {
|
||||
if (hCom != INVALID_HANDLE_VALUE)
|
||||
CloseHandle (hCom);
|
||||
if (hCom != INVALID_HANDLE_VALUE) CloseHandle (hCom);
|
||||
// We do not use own events so we don't have to clear them.
|
||||
}
|
||||
|
||||
Bitu lastChance;
|
||||
|
||||
void CDirectSerial::RXBufferEmpty () {
|
||||
DWORD dwRead;
|
||||
DWORD errors;
|
||||
Bit8u chRead;
|
||||
if (lastChance > 0) {
|
||||
receiveByte (ChanceChar);
|
||||
lastChance = 0;
|
||||
} else {
|
||||
// update RX
|
||||
if (ReadFile (hCom, &chRead, 1, &dwRead, NULL)) {
|
||||
if (dwRead != 0) {
|
||||
//LOG_MSG("UART 0x%x: RX 0x%x", base,chRead);
|
||||
receiveByte (chRead);
|
||||
void CDirectSerial::handleUpperEvent(Bit16u type) {
|
||||
|
||||
switch(type) {
|
||||
case SERIAL_POLLING_EVENT: {
|
||||
DWORD dwRead = 0;
|
||||
DWORD errors = 0;
|
||||
Bit8u chRead = 0;
|
||||
|
||||
setEvent(SERIAL_POLLING_EVENT, 1);
|
||||
if(!receiveblock) {
|
||||
if(((!(LSR&LSR_RX_DATA_READY_MASK)) || rx_retry>=rx_retry_max ))
|
||||
{
|
||||
rx_retry=0;
|
||||
if (ReadFile (hCom, &chRead, 1, &dwRead, NULL)) {
|
||||
if (dwRead) {
|
||||
receiveByte (chRead);
|
||||
setEvent(40, bytetime-0.03f); // receive timing
|
||||
receiveblock=true;
|
||||
}
|
||||
}
|
||||
} else rx_retry++;
|
||||
}
|
||||
// check for errors
|
||||
CheckErrors();
|
||||
// update Modem input line states
|
||||
updateMSR ();
|
||||
break;
|
||||
}
|
||||
case 40: {
|
||||
// receive time is up
|
||||
DWORD dwRead = 0;
|
||||
Bit8u chRead = 0;
|
||||
receiveblock=false;
|
||||
// check if there is something to receive
|
||||
if(((!(LSR&LSR_RX_DATA_READY_MASK)) || rx_retry>=rx_retry_max ))
|
||||
{
|
||||
rx_retry=0;
|
||||
if (ReadFile (hCom, &chRead, 1, &dwRead, NULL)) {
|
||||
if (dwRead) {
|
||||
receiveByte (chRead);
|
||||
setEvent(40, bytetime-0.03f); // receive timing
|
||||
receiveblock=true;
|
||||
}
|
||||
}
|
||||
} else rx_retry++;
|
||||
break;
|
||||
}
|
||||
case SERIAL_TX_EVENT: {
|
||||
DWORD dwRead = 0;
|
||||
Bit8u chRead = 0;
|
||||
if(!receiveblock) {
|
||||
if(((!(LSR&LSR_RX_DATA_READY_MASK)) || rx_retry>=rx_retry_max ))
|
||||
{
|
||||
rx_retry=0;
|
||||
if (ReadFile (hCom, &chRead, 1, &dwRead, NULL)) {
|
||||
if (dwRead) {
|
||||
receiveByte (chRead);
|
||||
setEvent(40, bytetime-0.03f); // receive timing
|
||||
receiveblock=true;
|
||||
}
|
||||
}
|
||||
} else rx_retry++;
|
||||
}
|
||||
ByteTransmitted();
|
||||
break;
|
||||
}
|
||||
case SERIAL_THR_EVENT: {
|
||||
ByteTransmitting();
|
||||
setEvent(SERIAL_TX_EVENT,bytetime+0.03f);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CDirectSerial::CheckErrors() {
|
||||
|
||||
DWORD errors=0;
|
||||
// check for errors
|
||||
if (ClearCommError (hCom, &errors, NULL))
|
||||
if (errors & (CE_BREAK | CE_FRAME | CE_RXPARITY)) {
|
||||
Bit8u errreg = 0;
|
||||
if (errors & CE_BREAK) {
|
||||
LOG_MSG ("Serial port at 0x%x: line error: break received.", base);
|
||||
errreg |= LSR_RX_BREAK_MASK;
|
||||
}
|
||||
if (errors & CE_FRAME) {
|
||||
LOG_MSG ("Serial port at 0x%x: line error: framing error.", base);
|
||||
errreg |= LSR_FRAMING_ERROR_MASK;
|
||||
}
|
||||
if (errors & CE_RXPARITY) {
|
||||
LOG_MSG ("Serial port at 0x%x: line error: parity error.", base);
|
||||
errreg |= LSR_PARITY_ERROR_MASK;
|
||||
}
|
||||
if (errors & CE_BREAK) errreg |= LSR_RX_BREAK_MASK;
|
||||
if (errors & CE_FRAME) errreg |= LSR_FRAMING_ERROR_MASK;
|
||||
if (errors & CE_RXPARITY) errreg |= LSR_PARITY_ERROR_MASK;
|
||||
receiveError (errreg);
|
||||
}
|
||||
}
|
||||
|
@ -135,45 +244,37 @@ void CDirectSerial::RXBufferEmpty () {
|
|||
/* updatePortConfig is called when emulated app changes the serial port **/
|
||||
/* parameters baudrate, stopbits, number of databits, parity. **/
|
||||
/*****************************************************************************/
|
||||
void CDirectSerial::updatePortConfig (Bit8u dll, Bit8u dlm, Bit8u lcr) {
|
||||
void CDirectSerial::updatePortConfig (Bit16u divider, Bit8u lcr) {
|
||||
Bit8u parity = 0;
|
||||
Bit8u bytelength = 0;
|
||||
Bit16u baudrate = 0;
|
||||
|
||||
// baud
|
||||
baudrate = dlm;
|
||||
baudrate = baudrate << 8;
|
||||
baudrate |= dll;
|
||||
if (baudrate <= 0x1)
|
||||
if (divider == 0x1)
|
||||
dcb.BaudRate = CBR_115200;
|
||||
else if (baudrate <= 0x2)
|
||||
else if (divider == 0x2)
|
||||
dcb.BaudRate = CBR_57600;
|
||||
else if (baudrate <= 0x3)
|
||||
else if (divider == 0x3)
|
||||
dcb.BaudRate = CBR_38400;
|
||||
else if (baudrate <= 0x6)
|
||||
else if (divider == 0x6)
|
||||
dcb.BaudRate = CBR_19200;
|
||||
else if (baudrate <= 0xc)
|
||||
else if (divider == 0xc)
|
||||
dcb.BaudRate = CBR_9600;
|
||||
else if (baudrate <= 0x18)
|
||||
else if (divider == 0x18)
|
||||
dcb.BaudRate = CBR_4800;
|
||||
else if (baudrate <= 0x30)
|
||||
else if (divider == 0x30)
|
||||
dcb.BaudRate = CBR_2400;
|
||||
else if (baudrate <= 0x60)
|
||||
else if (divider == 0x60)
|
||||
dcb.BaudRate = CBR_1200;
|
||||
else if (baudrate <= 0xc0)
|
||||
else if (divider == 0xc0)
|
||||
dcb.BaudRate = CBR_600;
|
||||
else if (baudrate <= 0x180)
|
||||
else if (divider == 0x180)
|
||||
dcb.BaudRate = CBR_300;
|
||||
else if (baudrate <= 0x417)
|
||||
else if (divider == 0x417)
|
||||
dcb.BaudRate = CBR_110;
|
||||
|
||||
// I read that windows can handle nonstandard baudrates:
|
||||
else
|
||||
dcb.BaudRate = 115200 / baudrate;
|
||||
|
||||
#ifdef SERIALPORT_DEBUGMSG
|
||||
LOG_MSG ("Serial port at %x: new baud rate: %d", base, dcb.BaudRate);
|
||||
#endif
|
||||
dcb.BaudRate = 115200 / divider;
|
||||
|
||||
// byte length
|
||||
bytelength = lcr & 0x3;
|
||||
|
@ -211,9 +312,25 @@ void CDirectSerial::updatePortConfig (Bit8u dll, Bit8u dlm, Bit8u lcr) {
|
|||
dcb.StopBits = ONESTOPBIT;
|
||||
}
|
||||
|
||||
if (!SetCommState (hCom, &dcb))
|
||||
LOG_MSG ("Serial port at 0x%x: API did not like the new values.", base);
|
||||
//LOG_MSG("Serial port at 0x%x: Port params changed: %d Baud", base,dcb.BaudRate);
|
||||
#ifdef SERIALPORT_DEBUGMSG
|
||||
LOG_MSG ("__________________________");
|
||||
LOG_MSG ("Serial%d: new baud rate: %d", COMNUMBER, dcb.BaudRate);
|
||||
LOG_MSG ("Serial%d: new bytelen: %d", COMNUMBER, dcb.ByteSize);
|
||||
LOG_MSG ("Serial%d: new parity: %d", COMNUMBER, dcb.Parity);
|
||||
LOG_MSG ("Serial%d: new stopbits: %d", COMNUMBER, dcb.StopBits);
|
||||
#endif
|
||||
|
||||
if (!SetCommState (hCom, &dcb)) {
|
||||
|
||||
#if SERIAL_DEBUG
|
||||
if(dbg_modemcontrol)
|
||||
fprintf(debugfp,"%12.3f serial mode not supported: rate=%d,LCR=%x.\r\n",
|
||||
PIC_FullIndex(),dcb.BaudRate,lcr);
|
||||
#endif
|
||||
|
||||
LOG_MSG ("Serial%d: Desired serial mode not supported (%d,%d,%d,%d",
|
||||
dcb.BaudRate,dcb.ByteSize,dcb.Parity,dcb.StopBits, COMNUMBER);
|
||||
}
|
||||
}
|
||||
|
||||
void CDirectSerial::updateMSR () {
|
||||
|
@ -226,153 +343,53 @@ void CDirectSerial::updateMSR () {
|
|||
#endif
|
||||
//return;
|
||||
}
|
||||
if (dptr & MS_CTS_ON)
|
||||
newmsr |= MSR_CTS_MASK;
|
||||
if (dptr & MS_DSR_ON)
|
||||
newmsr |= MSR_DSR_MASK;
|
||||
if (dptr & MS_RING_ON)
|
||||
newmsr |= MSR_RI_MASK;
|
||||
if (dptr & MS_RLSD_ON)
|
||||
newmsr |= MSR_CD_MASK;
|
||||
changeMSR (newmsr);
|
||||
setCTS((dptr & MS_CTS_ON)!=0);
|
||||
setDSR((dptr & MS_DSR_ON)!=0);
|
||||
setRI ((dptr & MS_RING_ON)!=0);
|
||||
setCD((dptr & MS_RLSD_ON)!=0);
|
||||
}
|
||||
|
||||
void CDirectSerial::transmitByte (Bit8u val) {
|
||||
void CDirectSerial::transmitByte (Bit8u val, bool first) {
|
||||
// mean bug: with break = 1, WriteFile will never return.
|
||||
if((LCR&LCR_BREAK_MASK) == 0) {
|
||||
|
||||
DWORD bytesWritten = 0;
|
||||
WriteFile (hCom, &val, 1, &bytesWritten, NULL);
|
||||
if (bytesWritten > 0) {
|
||||
ByteTransmitted ();
|
||||
//LOG_MSG("UART 0x%x: TX 0x%x", base,val);
|
||||
} else {
|
||||
LOG_MSG ("UART 0x%x: NO BYTE WRITTEN! PORT HANGS NOW!", base);
|
||||
}
|
||||
} else {
|
||||
// have a delay here, it's the only sense of sending
|
||||
// data with break=1
|
||||
Bitu ticks;
|
||||
Bitu elapsed = 0;
|
||||
ticks = GetTicks();
|
||||
|
||||
while(elapsed < 10) {
|
||||
elapsed = GetTicks() - ticks;
|
||||
}
|
||||
ByteTransmitted();
|
||||
if (bytesWritten != 1)
|
||||
LOG_MSG ("Serial%d: COM port error: write failed!", idnumber);
|
||||
}
|
||||
if(first) setEvent(SERIAL_THR_EVENT, bytetime/8);
|
||||
else setEvent(SERIAL_TX_EVENT, bytetime);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/* setBreak(val) switches break on or off **/
|
||||
/*****************************************************************************/
|
||||
|
||||
void CDirectSerial::setBreak (bool value) {
|
||||
//#ifdef SERIALPORT_DEBUGMSG
|
||||
//LOG_MSG("UART 0x%x: Break toggeled: %d", base, value);
|
||||
//#endif
|
||||
if (value)
|
||||
SetCommBreak (hCom);
|
||||
else
|
||||
ClearCommBreak (hCom);
|
||||
if (value) SetCommBreak (hCom);
|
||||
else ClearCommBreak (hCom);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/* updateModemControlLines(mcr) sets DTR and RTS. **/
|
||||
/*****************************************************************************/
|
||||
void CDirectSerial::updateModemControlLines ( /*Bit8u mcr */ ) {
|
||||
bool change = false;
|
||||
void CDirectSerial::setRTSDTR(bool rts, bool dtr) {
|
||||
if(rts) dcb.fRtsControl = RTS_CONTROL_ENABLE;
|
||||
else dcb.fRtsControl = RTS_CONTROL_DISABLE;
|
||||
if(dtr) dcb.fDtrControl = DTR_CONTROL_ENABLE;
|
||||
else dcb.fDtrControl = DTR_CONTROL_DISABLE;
|
||||
SetCommState (hCom, &dcb);
|
||||
|
||||
/*** DTR ***/
|
||||
if (CSerial::getDTR ()) { // DTR on
|
||||
if (dcb.fDtrControl == DTR_CONTROL_DISABLE) {
|
||||
dcb.fDtrControl = DTR_CONTROL_ENABLE;
|
||||
change = true;
|
||||
}
|
||||
} else {
|
||||
if (dcb.fDtrControl == DTR_CONTROL_ENABLE) {
|
||||
dcb.fDtrControl = DTR_CONTROL_DISABLE;
|
||||
change = true;
|
||||
}
|
||||
}
|
||||
/*** RTS ***/
|
||||
if (CSerial::getRTS ()) { // RTS on
|
||||
if (dcb.fRtsControl == RTS_CONTROL_DISABLE) {
|
||||
dcb.fRtsControl = RTS_CONTROL_ENABLE;
|
||||
change = true;
|
||||
}
|
||||
} else {
|
||||
if (dcb.fRtsControl == RTS_CONTROL_ENABLE) {
|
||||
dcb.fRtsControl = RTS_CONTROL_DISABLE;
|
||||
change = true;
|
||||
}
|
||||
}
|
||||
if (change)
|
||||
SetCommState (hCom, &dcb);
|
||||
}
|
||||
|
||||
void CDirectSerial::Timer2(void) {
|
||||
DWORD dwRead = 0;
|
||||
DWORD errors = 0;
|
||||
Bit8u chRead = 0;
|
||||
|
||||
|
||||
if (lastChance == 0) { // lastChance = 0
|
||||
if (CanReceiveByte ()) {
|
||||
if (ReadFile (hCom, &chRead, 1, &dwRead, NULL)) {
|
||||
if (dwRead)
|
||||
receiveByte (chRead);
|
||||
}
|
||||
} else {
|
||||
if (ReadFile (hCom, &chRead, 1, &dwRead, NULL)) {
|
||||
if (dwRead) {
|
||||
ChanceChar = chRead;
|
||||
lastChance++;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (lastChance > 10) {
|
||||
receiveByte (0); // this causes RX Overrun now
|
||||
lastChance = 0;
|
||||
// empty serial buffer
|
||||
dwRead = 1;
|
||||
while (dwRead > 0) { // throw away bytes in buffer
|
||||
ReadFile (hCom, &chRead, 1, &dwRead, NULL);
|
||||
}
|
||||
} else { // lastChance>0 // already one waiting
|
||||
if (CanReceiveByte ()) { // chance used
|
||||
receiveByte (ChanceChar);
|
||||
lastChance = 0;
|
||||
} else
|
||||
lastChance++;
|
||||
}
|
||||
|
||||
// check for errors
|
||||
if (ClearCommError (hCom, &errors, NULL))
|
||||
if (errors & (CE_BREAK | CE_FRAME | CE_RXPARITY)) {
|
||||
Bit8u errreg = 0;
|
||||
|
||||
if (errors & CE_BREAK) {
|
||||
LOG_MSG ("Serial port at 0x%x: line error: break received.", base);
|
||||
errreg |= LSR_RX_BREAK_MASK;
|
||||
}
|
||||
if (errors & CE_FRAME) {
|
||||
LOG_MSG ("Serial port at 0x%x: line error: framing error.", base);
|
||||
errreg |= LSR_FRAMING_ERROR_MASK;
|
||||
}
|
||||
if (errors & CE_RXPARITY) {
|
||||
LOG_MSG ("Serial port at 0x%x: line error: parity error.", base);
|
||||
errreg |= LSR_PARITY_ERROR_MASK;
|
||||
}
|
||||
|
||||
receiveError (errreg);
|
||||
}
|
||||
// update Modem input line states
|
||||
updateMSR ();
|
||||
void CDirectSerial::setRTS(bool val) {
|
||||
if(val) dcb.fRtsControl = RTS_CONTROL_ENABLE;
|
||||
else dcb.fRtsControl = RTS_CONTROL_DISABLE;
|
||||
SetCommState (hCom, &dcb);
|
||||
}
|
||||
void CDirectSerial::setDTR(bool val) {
|
||||
if(val) dcb.fDtrControl = DTR_CONTROL_ENABLE;
|
||||
else dcb.fDtrControl = DTR_CONTROL_DISABLE;
|
||||
SetCommState (hCom, &dcb);
|
||||
}
|
||||
|
||||
|
||||
#else /*linux and others oneday maybe */
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
/* $Id: directserial_win32.h,v 1.3 2007-01-08 19:45:41 qbix79 Exp $ */
|
||||
/* $Id: directserial_win32.h,v 1.4 2007-01-13 08:35:49 qbix79 Exp $ */
|
||||
|
||||
// include guard
|
||||
#ifndef DOSBOX_DIRECTSERIAL_WIN32_H
|
||||
|
@ -39,43 +39,27 @@ public:
|
|||
DCB dcb;
|
||||
BOOL fSuccess;
|
||||
|
||||
CDirectSerial(
|
||||
IO_ReadHandler* rh,
|
||||
IO_WriteHandler* wh,
|
||||
TIMER_TickHandler th,
|
||||
Bit16u baseAddr,
|
||||
Bit8u initIrq,
|
||||
Bit32u initBps,
|
||||
Bit8u bytesize,
|
||||
const char *parity,
|
||||
Bit8u stopbits,
|
||||
const char * realPort
|
||||
);
|
||||
|
||||
|
||||
CDirectSerial(Bitu id, CommandLine* cmd/*const char* configstring*/);
|
||||
~CDirectSerial();
|
||||
bool receiveblock; // It's not a block of data it rather blocks
|
||||
|
||||
Bitu rx_retry; // counter of retries
|
||||
|
||||
Bitu rx_retry_max; // how many POLL_EVENTS to wait before causing
|
||||
// a overrun error.
|
||||
|
||||
|
||||
void CheckErrors();
|
||||
|
||||
|
||||
Bitu lastChance; // If there is no space for new
|
||||
// received data, it gets a little chance
|
||||
Bit8u ChanceChar;
|
||||
|
||||
bool CanRecv(void);
|
||||
bool CanSend(void);
|
||||
|
||||
bool InstallationSuccessful; // check after constructing. If
|
||||
// something was wrong, delete it right away.
|
||||
|
||||
void RXBufferEmpty();
|
||||
|
||||
|
||||
void updatePortConfig(Bit8u dll, Bit8u dlm, Bit8u lcr);
|
||||
void updatePortConfig(Bit16u divider, Bit8u lcr);
|
||||
void updateMSR();
|
||||
void transmitByte(Bit8u val);
|
||||
void transmitByte(Bit8u val, bool first);
|
||||
void setBreak(bool value);
|
||||
void updateModemControlLines(/*Bit8u mcr*/);
|
||||
void Timer2(void);
|
||||
|
||||
void setRTSDTR(bool rts, bool dtr);
|
||||
void setRTS(bool val);
|
||||
void setDTR(bool val);
|
||||
void handleUpperEvent(Bit16u type);
|
||||
|
||||
};
|
||||
|
||||
|
|
318
src/hardware/serialport/misc_util.cpp
Normal file
318
src/hardware/serialport/misc_util.cpp
Normal file
|
@ -0,0 +1,318 @@
|
|||
#include "config.h"
|
||||
|
||||
#include "misc_util.h"
|
||||
|
||||
#if C_MODEM
|
||||
|
||||
/*****************************************************************************/
|
||||
// C++ SDLnet wrapper
|
||||
|
||||
// Socket inheritance
|
||||
#ifdef LINUX
|
||||
#define CAPWORD (NETWRAPPER_TCP|NETWRAPPER_TCP_NATIVESOCKET)
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#define SOCKET int
|
||||
|
||||
#elif defined WIN32
|
||||
#define CAPWORD (NETWRAPPER_TCP|NETWRAPPER_TCP_NATIVESOCKET)
|
||||
#include <winsock.h>
|
||||
typedef int socklen_t;
|
||||
|
||||
#else
|
||||
#define CAPWORD NETWRAPPER_TCP
|
||||
#endif
|
||||
|
||||
struct _TCPsocketX {
|
||||
int ready;
|
||||
SOCKET channel;
|
||||
IPaddress remoteAddress;
|
||||
IPaddress localAddress;
|
||||
int sflag;
|
||||
};
|
||||
|
||||
Bit32u Netwrapper_GetCapabilities()
|
||||
{
|
||||
Bit32u retval=0;
|
||||
retval = CAPWORD;
|
||||
return retval;
|
||||
}
|
||||
|
||||
#ifdef NATIVESOCKETS
|
||||
TCPClientSocket::TCPClientSocket(int platformsocket) {
|
||||
sendbuffer=0;
|
||||
nativetcpstruct = new Bit8u[sizeof(struct _TCPsocketX)];
|
||||
|
||||
mysock = (TCPsocket)nativetcpstruct;
|
||||
isopen = false;
|
||||
if(!SDLNetInited) {
|
||||
if(SDLNet_Init()==-1) {
|
||||
LOG_MSG("SDLNet_Init failed: %s\n", SDLNet_GetError());
|
||||
return;
|
||||
}
|
||||
SDLNetInited = true;
|
||||
}
|
||||
// fill the SDL socket manually
|
||||
((struct _TCPsocketX*)nativetcpstruct)->ready=0;
|
||||
((struct _TCPsocketX*)nativetcpstruct)->sflag=0;
|
||||
((struct _TCPsocketX*)nativetcpstruct)->channel=platformsocket;
|
||||
sockaddr_in sa;
|
||||
socklen_t sz;
|
||||
sz=sizeof(sa);
|
||||
if(getpeername(platformsocket, (sockaddr *)(&sa), &sz)==0) {
|
||||
((struct _TCPsocketX*)nativetcpstruct)->
|
||||
remoteAddress.host=/*ntohl(*/sa.sin_addr.s_addr;//);
|
||||
((struct _TCPsocketX*)nativetcpstruct)->
|
||||
remoteAddress.port=/*ntohs(*/sa.sin_port;//);
|
||||
}
|
||||
else {
|
||||
mysock=0;
|
||||
return;
|
||||
}
|
||||
sz=sizeof(sa);
|
||||
if(getsockname(platformsocket, (sockaddr *)(&sa), &sz)==0) {
|
||||
((struct _TCPsocketX*)nativetcpstruct)->
|
||||
localAddress.host=/*ntohl(*/sa.sin_addr.s_addr;//);
|
||||
((struct _TCPsocketX*)nativetcpstruct)->
|
||||
localAddress.port=/*ntohs(*/sa.sin_port;//);
|
||||
}
|
||||
else {
|
||||
mysock=0;
|
||||
return;
|
||||
}
|
||||
if(mysock!=0) {
|
||||
listensocketset = SDLNet_AllocSocketSet(1);
|
||||
if(!listensocketset) return;
|
||||
SDLNet_TCP_AddSocket(listensocketset, mysock);
|
||||
isopen=true;
|
||||
return;
|
||||
}
|
||||
mysock=0;
|
||||
return;
|
||||
}
|
||||
#endif // NATIVESOCKETS
|
||||
|
||||
TCPClientSocket::TCPClientSocket(TCPsocket source) {
|
||||
#ifdef NATIVESOCKETS
|
||||
nativetcpstruct=0;
|
||||
#endif
|
||||
sendbuffer=0;
|
||||
isopen = false;
|
||||
if(!SDLNetInited) {
|
||||
if(SDLNet_Init()==-1) {
|
||||
LOG_MSG("SDLNet_Init failed: %s\n", SDLNet_GetError());
|
||||
return;
|
||||
}
|
||||
SDLNetInited = true;
|
||||
}
|
||||
|
||||
mysock=0;
|
||||
listensocketset=0;
|
||||
if(source!=0) {
|
||||
mysock = source;
|
||||
listensocketset = SDLNet_AllocSocketSet(1);
|
||||
if(!listensocketset) return;
|
||||
SDLNet_TCP_AddSocket(listensocketset, source);
|
||||
|
||||
isopen=true;
|
||||
}
|
||||
}
|
||||
TCPClientSocket::TCPClientSocket(const char* destination, Bit16u port) {
|
||||
#ifdef NATIVESOCKETS
|
||||
nativetcpstruct=0;
|
||||
#endif
|
||||
sendbuffer=0;
|
||||
isopen = false;
|
||||
if(!SDLNetInited) {
|
||||
if(SDLNet_Init()==-1) {
|
||||
LOG_MSG("SDLNet_Init failed: %s\n", SDLNet_GetError());
|
||||
return;
|
||||
}
|
||||
SDLNetInited = true;
|
||||
}
|
||||
mysock=0;
|
||||
listensocketset=0;
|
||||
|
||||
IPaddress openip;
|
||||
if (!SDLNet_ResolveHost(&openip,destination,port)) {
|
||||
listensocketset = SDLNet_AllocSocketSet(1);
|
||||
if(!listensocketset) return;
|
||||
mysock = SDLNet_TCP_Open(&openip);
|
||||
if(!mysock) return;
|
||||
SDLNet_TCP_AddSocket(listensocketset, mysock);
|
||||
isopen=true;
|
||||
}
|
||||
}
|
||||
|
||||
TCPClientSocket::~TCPClientSocket() {
|
||||
|
||||
if(sendbuffer) delete [] sendbuffer;
|
||||
#ifdef NATIVESOCKETS
|
||||
if(nativetcpstruct) delete [] nativetcpstruct;
|
||||
else
|
||||
#endif
|
||||
if(mysock) {
|
||||
if(listensocketset) SDLNet_TCP_DelSocket(listensocketset,mysock);
|
||||
SDLNet_TCP_Close(mysock);
|
||||
}
|
||||
|
||||
if(listensocketset) SDLNet_FreeSocketSet(listensocketset);
|
||||
}
|
||||
bool TCPClientSocket::GetRemoteAddressString(Bit8u* buffer) {
|
||||
IPaddress* remote_ip;
|
||||
Bit8u b1, b2, b3, b4;
|
||||
remote_ip=SDLNet_TCP_GetPeerAddress(mysock);
|
||||
if(!remote_ip) return false;
|
||||
b4=remote_ip->host>>24;
|
||||
b3=(remote_ip->host>>16)&0xff;
|
||||
b2=(remote_ip->host>>8)&0xff;
|
||||
b1=remote_ip->host&0xff;
|
||||
sprintf((char*)buffer,"%u.%u.%u.%u",b1,b2,b3,b4);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool TCPClientSocket::ReceiveArray(Bit8u* data, Bitu* size) {
|
||||
if(SDLNet_CheckSockets(listensocketset,0))
|
||||
{
|
||||
Bitu retval = SDLNet_TCP_Recv(mysock, data, *size);
|
||||
if(retval<1) {
|
||||
isopen=false;
|
||||
*size=0;
|
||||
return false;
|
||||
} else {
|
||||
*size=retval;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else {
|
||||
*size=0;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Bits TCPClientSocket::GetcharNonBlock() {
|
||||
// return:
|
||||
// -1: no data
|
||||
// -2: socket closed
|
||||
// 0..255: data
|
||||
if(SDLNet_CheckSockets(listensocketset,0))
|
||||
{
|
||||
Bitu retval =0;
|
||||
if(SDLNet_TCP_Recv(mysock, &retval, 1)!=1) {
|
||||
isopen=false;
|
||||
return -2;
|
||||
} else return retval;
|
||||
}
|
||||
else return -1;
|
||||
}
|
||||
bool TCPClientSocket::Putchar(Bit8u data) {
|
||||
if(SDLNet_TCP_Send(mysock, &data, 1)!=1) {
|
||||
isopen=false;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool TCPClientSocket::SendArray(Bit8u* data, Bitu bufsize) {
|
||||
if(SDLNet_TCP_Send(mysock, data, bufsize)!=bufsize) {
|
||||
isopen=false;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool TCPClientSocket::SendByteBuffered(Bit8u data) {
|
||||
|
||||
if(sendbufferindex==(sendbuffersize-1)) {
|
||||
// buffer is full, get rid of it
|
||||
sendbuffer[sendbufferindex]=data;
|
||||
sendbufferindex=0;
|
||||
|
||||
if(SDLNet_TCP_Send(mysock, sendbuffer, sendbuffersize)!=sendbuffersize) {
|
||||
isopen=false;
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
sendbuffer[sendbufferindex]=data;
|
||||
sendbufferindex++;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
/*
|
||||
bool TCPClientSocket::SendArrayBuffered(Bit8u* data, Bitu bufsize) {
|
||||
|
||||
Bitu bytes
|
||||
while(
|
||||
|
||||
// first case, buffer already full
|
||||
/*if(sendbufferindex==(sendbuffersize-1)) {
|
||||
// buffer is full, get rid of it
|
||||
sendbuffer[sendbufferindex]=data;
|
||||
sendbufferindex=0;
|
||||
|
||||
if(SDLNet_TCP_Send(mysock, sendbuffer, sendbuffersize)!=sendbuffersize) {
|
||||
isopen=false;
|
||||
return false;
|
||||
}
|
||||
}*/
|
||||
//}
|
||||
|
||||
void TCPClientSocket::FlushBuffer() {
|
||||
if(sendbufferindex) {
|
||||
if(SDLNet_TCP_Send(mysock, sendbuffer,
|
||||
sendbufferindex)!=sendbufferindex) {
|
||||
isopen=false;
|
||||
return;
|
||||
}
|
||||
sendbufferindex=0;
|
||||
}
|
||||
}
|
||||
|
||||
void TCPClientSocket::SetSendBufferSize(Bitu bufsize) {
|
||||
if(sendbuffer) delete [] sendbuffer;
|
||||
sendbuffer = new Bit8u[bufsize];
|
||||
sendbuffersize=bufsize;
|
||||
sendbufferindex=0;
|
||||
}
|
||||
|
||||
|
||||
TCPServerSocket::TCPServerSocket(Bit16u port)
|
||||
{
|
||||
isopen = false;
|
||||
mysock = 0;
|
||||
if(!SDLNetInited) {
|
||||
if(SDLNet_Init()==-1) {
|
||||
LOG_MSG("SDLNet_Init failed: %s\n", SDLNet_GetError());
|
||||
return;
|
||||
}
|
||||
SDLNetInited = true;
|
||||
}
|
||||
if (port) {
|
||||
IPaddress listen_ip;
|
||||
SDLNet_ResolveHost(&listen_ip, NULL, port);
|
||||
mysock=SDLNet_TCP_Open(&listen_ip);
|
||||
if(!mysock) return;
|
||||
}
|
||||
else return;
|
||||
isopen = true;
|
||||
}
|
||||
|
||||
TCPServerSocket::~TCPServerSocket() {
|
||||
if(mysock) SDLNet_TCP_Close(mysock);
|
||||
}
|
||||
|
||||
TCPClientSocket* TCPServerSocket::Accept() {
|
||||
|
||||
TCPsocket new_tcpsock;
|
||||
|
||||
new_tcpsock=SDLNet_TCP_Accept(mysock);
|
||||
if(!new_tcpsock) {
|
||||
//printf("SDLNet_TCP_Accept: %s\n", SDLNet_GetError());
|
||||
return 0;
|
||||
}
|
||||
|
||||
return new TCPClientSocket(new_tcpsock);
|
||||
}
|
||||
#endif // #if C_MODEM
|
79
src/hardware/serialport/misc_util.h
Normal file
79
src/hardware/serialport/misc_util.h
Normal file
|
@ -0,0 +1,79 @@
|
|||
#ifndef SDLNETWRAPPER_H
|
||||
#define SDLNETWRAPPER_H
|
||||
|
||||
#if C_MODEM
|
||||
|
||||
#include "SDL_net.h"
|
||||
#include "support.h"
|
||||
|
||||
#ifdef LINUX
|
||||
#define NATIVESOCKETS
|
||||
|
||||
#elif defined WIN32
|
||||
#define NATIVESOCKETS
|
||||
|
||||
#else
|
||||
#endif
|
||||
|
||||
// Netwrapper Capabilities
|
||||
#define NETWRAPPER_TCP 1
|
||||
#define NETWRAPPER_TCP_NATIVESOCKET 2
|
||||
|
||||
Bit32u Netwrapper_GetCapabilities();
|
||||
|
||||
|
||||
class TCPClientSocket {
|
||||
public:
|
||||
TCPClientSocket(TCPsocket source);
|
||||
TCPClientSocket(const char* destination, Bit16u port);
|
||||
#ifdef NATIVESOCKETS
|
||||
void* nativetcpstruct;
|
||||
TCPClientSocket(int platformsocket);
|
||||
#endif
|
||||
~TCPClientSocket();
|
||||
|
||||
// return:
|
||||
// -1: no data
|
||||
// -2: socket closed
|
||||
// >0: data char
|
||||
Bits GetcharNonBlock();
|
||||
|
||||
|
||||
bool Putchar(Bit8u data);
|
||||
bool SendArray(Bit8u* data, Bitu bufsize);
|
||||
bool ReceiveArray(Bit8u* data, Bitu* size);
|
||||
bool isopen;
|
||||
|
||||
bool GetRemoteAddressString(Bit8u* buffer);
|
||||
|
||||
void FlushBuffer();
|
||||
void SetSendBufferSize(Bitu bufsize);
|
||||
|
||||
// buffered send functions
|
||||
bool SendByteBuffered(Bit8u data);
|
||||
bool SendArrayBuffered(Bit8u* data, Bitu bufsize);
|
||||
|
||||
private:
|
||||
TCPsocket mysock;
|
||||
SDLNet_SocketSet listensocketset;
|
||||
|
||||
// Items for send buffering
|
||||
Bitu sendbuffersize;
|
||||
Bitu sendbufferindex;
|
||||
|
||||
Bit8u* sendbuffer;
|
||||
};
|
||||
|
||||
class TCPServerSocket {
|
||||
public:
|
||||
bool isopen;
|
||||
TCPsocket mysock;
|
||||
TCPServerSocket(Bit16u port);
|
||||
~TCPServerSocket();
|
||||
TCPClientSocket* Accept();
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
#endif //#if C_MODEM
|
496
src/hardware/serialport/nullmodem.cpp
Normal file
496
src/hardware/serialport/nullmodem.cpp
Normal file
|
@ -0,0 +1,496 @@
|
|||
/*
|
||||
* Copyright (C) 2002-2007 The DOSBox Team
|
||||
*
|
||||
* 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
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#include "dosbox.h"
|
||||
|
||||
#if C_MODEM
|
||||
|
||||
#include "setup.h" // CommandLine
|
||||
#include "serialport.h"
|
||||
#include "nullmodem.h"
|
||||
|
||||
CNullModem::CNullModem(Bitu id, CommandLine* cmd):CSerial (id, cmd) {
|
||||
Bitu temptcpport=23;
|
||||
memset(&telClient, 0, sizeof(telClient));
|
||||
InstallationSuccessful = false;
|
||||
serversocket = 0;
|
||||
clientsocket = 0;
|
||||
serverport = 0;
|
||||
clientport = 0;
|
||||
|
||||
rx_retry = 0;
|
||||
rx_retry_max = 100;
|
||||
|
||||
tx_gather = 12;
|
||||
|
||||
dtrrespect=false;
|
||||
tx_block=false;
|
||||
receiveblock=false;
|
||||
transparent=false;
|
||||
telnet=false;
|
||||
|
||||
Bitu bool_temp=0;
|
||||
|
||||
// usedtr: The nullmodem will
|
||||
// 1) when it is client connect to the server not immediately but
|
||||
// as soon as a modem-aware application is started (DTR is switched on).
|
||||
// 2) only transfer data when DTR is on.
|
||||
if(getBituSubstring("usedtr:", &bool_temp, cmd)) {
|
||||
if(bool_temp==1) {
|
||||
dtrrespect=true;
|
||||
transparent=true;
|
||||
}
|
||||
}
|
||||
// transparent: don't add additional handshake control.
|
||||
if(getBituSubstring("transparent:", &bool_temp, cmd)) {
|
||||
if(bool_temp==1) transparent=true;
|
||||
else transparent=false;
|
||||
}
|
||||
// telnet: interpret telnet commands.
|
||||
if(getBituSubstring("telnet:", &bool_temp, cmd)) {
|
||||
if(bool_temp==1) {
|
||||
transparent=true;
|
||||
telnet=true;
|
||||
}
|
||||
}
|
||||
// rxdelay: How many milliseconds to wait before causing an
|
||||
// overflow when the application is unresponsive.
|
||||
if(getBituSubstring("rxdelay:", &rx_retry_max, cmd)) {
|
||||
if(!(rx_retry_max<=10000)) {
|
||||
rx_retry_max=50;
|
||||
}
|
||||
}
|
||||
// txdelay: How many milliseconds to wait before sending data.
|
||||
// This reduces network overhead quite a lot.
|
||||
if(getBituSubstring("txdelay:", &tx_gather, cmd)) {
|
||||
if(!(tx_gather<=500)) {
|
||||
tx_gather=12;
|
||||
}
|
||||
}
|
||||
// port is for both server and client
|
||||
if(getBituSubstring("port:", &temptcpport, cmd)) {
|
||||
if(!(temptcpport>0&&temptcpport<65536)) {
|
||||
temptcpport=23;
|
||||
}
|
||||
}
|
||||
// socket inheritance
|
||||
if(getBituSubstring("inhsocket:", &bool_temp, cmd)) {
|
||||
if(Netwrapper_GetCapabilities()&NETWRAPPER_TCP_NATIVESOCKET) {
|
||||
if(bool_temp==1) {
|
||||
int sock;
|
||||
if (control->cmdline->FindInt("-socket",sock,true)) {
|
||||
dtrrespect=false;
|
||||
transparent=true;
|
||||
// custom connect
|
||||
Bit8u peernamebuf[16];
|
||||
LOG_MSG("inheritance port: %d",sock);
|
||||
clientsocket = new TCPClientSocket(sock);
|
||||
if(!clientsocket->isopen) {
|
||||
LOG_MSG("Serial%d: Connection failed.",COMNUMBER);
|
||||
delete clientsocket;
|
||||
clientsocket=0;
|
||||
return;
|
||||
}
|
||||
clientsocket->SetSendBufferSize(256);
|
||||
clientsocket->GetRemoteAddressString(peernamebuf);
|
||||
// transmit the line status
|
||||
if(!transparent) setRTSDTR(getRTS(), getDTR());
|
||||
|
||||
LOG_MSG("Serial%d: Connected to %s",COMNUMBER,peernamebuf);
|
||||
setEvent(SERIAL_POLLING_EVENT, 1);
|
||||
|
||||
CSerial::Init_Registers ();
|
||||
InstallationSuccessful = true;
|
||||
|
||||
setCTS(true);
|
||||
setDSR(true);
|
||||
setRI (false);
|
||||
setCD (true);
|
||||
return;
|
||||
} else {
|
||||
LOG_MSG("Serial%d: -socket start parameter missing.",COMNUMBER);
|
||||
return;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
LOG_MSG("Serial%d: socket inheritance not supported on this platform.",
|
||||
COMNUMBER);
|
||||
return;
|
||||
}
|
||||
}
|
||||
std::string tmpstring;
|
||||
if(cmd->FindStringBegin("server:",tmpstring,false)) {
|
||||
// we are a client
|
||||
const char* hostnamechar=tmpstring.c_str();
|
||||
Bitu hostlen=strlen(hostnamechar)+1;
|
||||
if(hostlen>sizeof(hostnamebuffer)) {
|
||||
hostlen=sizeof(hostnamebuffer);
|
||||
hostnamebuffer[sizeof(hostnamebuffer)-1]=0;
|
||||
}
|
||||
memcpy(hostnamebuffer,hostnamechar,hostlen);
|
||||
clientport=temptcpport;
|
||||
if(dtrrespect) {
|
||||
// we connect as soon as DTR is switched on
|
||||
setEvent(SERIAL_NULLMODEM_DTR_EVENT, 50);
|
||||
LOG_MSG("Serial%d: Waiting for DTR...",COMNUMBER);
|
||||
} else ClientConnect();
|
||||
} else {
|
||||
// we are a server
|
||||
serverport = (Bit16u)temptcpport;
|
||||
serversocket = new TCPServerSocket(serverport);
|
||||
if(!serversocket->isopen) return;
|
||||
LOG_MSG("Serial%d: Nullmodem server waiting for connection on port %d...",
|
||||
COMNUMBER,serverport);
|
||||
setEvent(SERIAL_SERVER_POLLING_EVENT, 50);
|
||||
}
|
||||
|
||||
// ....
|
||||
|
||||
CSerial::Init_Registers ();
|
||||
InstallationSuccessful = true;
|
||||
|
||||
setCTS(dtrrespect||transparent);
|
||||
setDSR(dtrrespect||transparent);
|
||||
setRI (false);
|
||||
setCD (dtrrespect);
|
||||
}
|
||||
|
||||
CNullModem::~CNullModem () {
|
||||
if(serversocket) delete serversocket;
|
||||
if(clientsocket) delete clientsocket;
|
||||
// remove events
|
||||
for(Bitu i = SERIAL_BASE_EVENT_COUNT+1;
|
||||
i <= SERIAL_NULLMODEM_EVENT_COUNT; i++)
|
||||
removeEvent(i);
|
||||
}
|
||||
|
||||
void CNullModem::WriteChar(Bit8u data) {
|
||||
|
||||
if(clientsocket)clientsocket->SendByteBuffered(data);
|
||||
if(!tx_block) {
|
||||
//LOG_MSG("setevreduct");
|
||||
setEvent(SERIAL_TX_REDUCTION, (float)tx_gather);
|
||||
tx_block=true;
|
||||
}
|
||||
}
|
||||
|
||||
Bits CNullModem::readChar() {
|
||||
|
||||
Bits rxchar = clientsocket->GetcharNonBlock();
|
||||
if(telnet && rxchar>=0) return TelnetEmulation(rxchar);
|
||||
else if(rxchar==0xff && !transparent) {// escape char
|
||||
// get the next char
|
||||
Bits rxchar = clientsocket->GetcharNonBlock();
|
||||
if(rxchar==0xff) return rxchar; // 0xff 0xff -> 0xff was meant
|
||||
rxchar&0x1? setCTS(true) : setCTS(false);
|
||||
rxchar&0x2? setDSR(true) : setDSR(false);
|
||||
if(rxchar&0x4) receiveError(0x10);
|
||||
return -1; // no "payload" received
|
||||
} else return rxchar;
|
||||
}
|
||||
|
||||
void CNullModem::ClientConnect(){
|
||||
Bit8u peernamebuf[16];
|
||||
clientsocket = new TCPClientSocket((char*)hostnamebuffer,
|
||||
(Bit16u)clientport);
|
||||
if(!clientsocket->isopen) {
|
||||
LOG_MSG("Serial%d: Connection failed.",idnumber+1);
|
||||
delete clientsocket;
|
||||
clientsocket=0;
|
||||
return;
|
||||
}
|
||||
clientsocket->SetSendBufferSize(256);
|
||||
clientsocket->GetRemoteAddressString(peernamebuf);
|
||||
// transmit the line status
|
||||
if(!transparent) setRTSDTR(getRTS(), getDTR());
|
||||
|
||||
LOG_MSG("Serial%d: Connected to %s",idnumber+1,peernamebuf);
|
||||
setEvent(SERIAL_POLLING_EVENT, 1);
|
||||
}
|
||||
|
||||
void CNullModem::Disconnect() {
|
||||
// it was disconnected; free the socket and restart the server socket
|
||||
LOG_MSG("Serial%d: Disconnected.",idnumber+1);
|
||||
delete clientsocket;
|
||||
clientsocket=0;
|
||||
setDTR(false);
|
||||
setCTS(false);
|
||||
if(serverport) {
|
||||
serversocket = new TCPServerSocket(serverport);
|
||||
if(serversocket->isopen)
|
||||
setEvent(SERIAL_SERVER_POLLING_EVENT, 50);
|
||||
else delete serversocket;
|
||||
}
|
||||
}
|
||||
|
||||
void CNullModem::handleUpperEvent(Bit16u type) {
|
||||
|
||||
switch(type) {
|
||||
case SERIAL_POLLING_EVENT: {
|
||||
// periodically check if new data arrived, disconnect
|
||||
// if required. Add it back.
|
||||
if(!receiveblock && clientsocket) {
|
||||
if(((!(LSR&LSR_RX_DATA_READY_MASK)) || rx_retry>=rx_retry_max )
|
||||
&&(!dtrrespect | (dtrrespect&& getDTR()) )) {
|
||||
rx_retry=0;
|
||||
Bits rxchar = readChar();
|
||||
if(rxchar>=0) {
|
||||
receiveblock=true;
|
||||
setEvent(SERIAL_RX_EVENT, bytetime-0.01f);
|
||||
receiveByte((Bit8u)rxchar);
|
||||
}
|
||||
else if(rxchar==-2) Disconnect();
|
||||
else setEvent(SERIAL_POLLING_EVENT, 1);
|
||||
} else {
|
||||
rx_retry++;
|
||||
setEvent(SERIAL_POLLING_EVENT, 1);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case SERIAL_RX_EVENT: {
|
||||
// receive time is up, try to receive another byte.
|
||||
receiveblock=false;
|
||||
|
||||
if((!(LSR&LSR_RX_DATA_READY_MASK) || rx_retry>=rx_retry_max)
|
||||
&&(!dtrrespect | (dtrrespect&& getDTR()) )
|
||||
) {
|
||||
rx_retry=0;
|
||||
Bits rxchar = readChar();
|
||||
if(rxchar>=0) {
|
||||
receiveblock=true;
|
||||
setEvent(SERIAL_RX_EVENT, bytetime-0.01f);
|
||||
receiveByte((Bit8u)rxchar);
|
||||
}
|
||||
else if(rxchar==-2) Disconnect();
|
||||
else setEvent(SERIAL_POLLING_EVENT, 1);
|
||||
} else {
|
||||
setEvent(SERIAL_POLLING_EVENT, 1);
|
||||
rx_retry++;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case SERIAL_TX_EVENT: {
|
||||
ByteTransmitted();
|
||||
break;
|
||||
}
|
||||
case SERIAL_THR_EVENT: {
|
||||
ByteTransmitting();
|
||||
// actually send it
|
||||
setEvent(SERIAL_TX_EVENT,bytetime+0.01f);
|
||||
break;
|
||||
}
|
||||
case SERIAL_SERVER_POLLING_EVENT: {
|
||||
// As long as nothing is connected to out server poll the
|
||||
// connection.
|
||||
if((clientsocket=serversocket->Accept())) {
|
||||
Bit8u peeripbuf[16];
|
||||
clientsocket->GetRemoteAddressString(peeripbuf);
|
||||
LOG_MSG("Serial%d: A client (%s) has connected.",idnumber+1,peeripbuf);
|
||||
// new socket found...
|
||||
clientsocket->SetSendBufferSize(256);
|
||||
setEvent(SERIAL_POLLING_EVENT, 1);
|
||||
|
||||
// we don't accept further connections
|
||||
delete serversocket;
|
||||
serversocket=0;
|
||||
|
||||
// transmit the line status
|
||||
setRTSDTR(getRTS(), getDTR());
|
||||
} else {
|
||||
// continue looking
|
||||
setEvent(SERIAL_SERVER_POLLING_EVENT, 50);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case SERIAL_TX_REDUCTION: {
|
||||
// Flush the data in the transmitting buffer.
|
||||
if(clientsocket) clientsocket->FlushBuffer();
|
||||
tx_block=false;
|
||||
break;
|
||||
}
|
||||
case SERIAL_NULLMODEM_DTR_EVENT: {
|
||||
if(getDTR()) ClientConnect();
|
||||
else setEvent(SERIAL_NULLMODEM_DTR_EVENT,50);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/* updatePortConfig is called when emulated app changes the serial port **/
|
||||
/* parameters baudrate, stopbits, number of databits, parity. **/
|
||||
/*****************************************************************************/
|
||||
void CNullModem::updatePortConfig (Bit16u divider, Bit8u lcr) {
|
||||
|
||||
}
|
||||
|
||||
void CNullModem::updateMSR () {
|
||||
|
||||
}
|
||||
|
||||
void CNullModem::transmitByte (Bit8u val, bool first) {
|
||||
|
||||
// transmit it later in THR_Event
|
||||
if(first) {
|
||||
setEvent(SERIAL_THR_EVENT, bytetime/8);
|
||||
}
|
||||
else {
|
||||
//if(clientsocket) clientsocket->Putchar(val);
|
||||
setEvent(SERIAL_TX_EVENT, bytetime);
|
||||
}
|
||||
/*****************************/
|
||||
if(val==0xff) WriteChar(0xff);
|
||||
|
||||
WriteChar(val);
|
||||
}
|
||||
|
||||
Bits CNullModem::TelnetEmulation(Bit8u data) {
|
||||
Bit8u response[3];
|
||||
if(telClient.inIAC) {
|
||||
if(telClient.recCommand) {
|
||||
if((data != 0) && (data != 1) && (data != 3)) {
|
||||
LOG_MSG("Serial%d: Unrecognized telnet option %d",COMNUMBER, data);
|
||||
if(telClient.command>250) {
|
||||
/* Reject anything we don't recognize */
|
||||
response[0]=0xff;
|
||||
response[1]=252;
|
||||
response[2]=data; /* We won't do crap! */
|
||||
if(clientsocket) clientsocket->SendArray(response, 3);
|
||||
}
|
||||
}
|
||||
switch(telClient.command) {
|
||||
case 251: /* Will */
|
||||
if(data == 0) telClient.binary[TEL_SERVER] = true;
|
||||
if(data == 1) telClient.echo[TEL_SERVER] = true;
|
||||
if(data == 3) telClient.supressGA[TEL_SERVER] = true;
|
||||
break;
|
||||
case 252: /* Won't */
|
||||
if(data == 0) telClient.binary[TEL_SERVER] = false;
|
||||
if(data == 1) telClient.echo[TEL_SERVER] = false;
|
||||
if(data == 3) telClient.supressGA[TEL_SERVER] = false;
|
||||
break;
|
||||
case 253: /* Do */
|
||||
if(data == 0) {
|
||||
telClient.binary[TEL_CLIENT] = true;
|
||||
response[0]=0xff;
|
||||
response[1]=251;
|
||||
response[2]=0; /* Will do binary transfer */
|
||||
if(clientsocket) clientsocket->SendArray(response, 3);
|
||||
}
|
||||
if(data == 1) {
|
||||
telClient.echo[TEL_CLIENT] = false;
|
||||
response[0]=0xff;
|
||||
response[1]=252;
|
||||
response[2]=1; /* Won't echo (too lazy) */
|
||||
if(clientsocket) clientsocket->SendArray(response, 3);
|
||||
}
|
||||
if(data == 3) {
|
||||
telClient.supressGA[TEL_CLIENT] = true;
|
||||
response[0]=0xff;
|
||||
response[1]=251;
|
||||
response[2]=3; /* Will Suppress GA */
|
||||
if(clientsocket) clientsocket->SendArray(response, 3);
|
||||
}
|
||||
break;
|
||||
case 254: /* Don't */
|
||||
if(data == 0) {
|
||||
telClient.binary[TEL_CLIENT] = false;
|
||||
response[0]=0xff;
|
||||
response[1]=252;
|
||||
response[2]=0; /* Won't do binary transfer */
|
||||
if(clientsocket) clientsocket->SendArray(response, 3);
|
||||
}
|
||||
if(data == 1) {
|
||||
telClient.echo[TEL_CLIENT] = false;
|
||||
response[0]=0xff;
|
||||
response[1]=252;
|
||||
response[2]=1; /* Won't echo (fine by me) */
|
||||
if(clientsocket) clientsocket->SendArray(response, 3);
|
||||
}
|
||||
if(data == 3) {
|
||||
telClient.supressGA[TEL_CLIENT] = true;
|
||||
response[0]=0xff;
|
||||
response[1]=251;
|
||||
response[2]=3; /* Will Suppress GA (too lazy) */
|
||||
if(clientsocket) clientsocket->SendArray(response, 3);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
LOG_MSG("MODEM: Telnet client sent IAC %d", telClient.command);
|
||||
break;
|
||||
}
|
||||
telClient.inIAC = false;
|
||||
telClient.recCommand = false;
|
||||
return -1; //continue;
|
||||
} else {
|
||||
if(data==249) {
|
||||
/* Go Ahead received */
|
||||
telClient.inIAC = false;
|
||||
return -1; //continue;
|
||||
}
|
||||
telClient.command = data;
|
||||
telClient.recCommand = true;
|
||||
|
||||
if((telClient.binary[TEL_SERVER]) && (data == 0xff)) {
|
||||
/* Binary data with value of 255 */
|
||||
telClient.inIAC = false;
|
||||
telClient.recCommand = false;
|
||||
return 0xff;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if(data == 0xff) {
|
||||
telClient.inIAC = true;
|
||||
return -1;
|
||||
}
|
||||
return data;
|
||||
}
|
||||
return -1; // ???
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
/* setBreak(val) switches break on or off **/
|
||||
/*****************************************************************************/
|
||||
|
||||
void CNullModem::setBreak (bool value) {
|
||||
CNullModem::setRTSDTR(getRTS(), getDTR());
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/* updateModemControlLines(mcr) sets DTR and RTS. **/
|
||||
/*****************************************************************************/
|
||||
void CNullModem::setRTSDTR(bool xrts, bool xdtr) {
|
||||
if(!transparent) {
|
||||
Bit8u control[2];
|
||||
control[0]=0xff;
|
||||
control[1]=0x0;
|
||||
if(xrts) control[1]|=1;
|
||||
if(xdtr) control[1]|=2;
|
||||
if(LCR&LCR_BREAK_MASK) control[1]|=4;
|
||||
if(clientsocket) clientsocket->SendArray(control, 2);
|
||||
}
|
||||
}
|
||||
void CNullModem::setRTS(bool val) {
|
||||
setRTSDTR(val, getDTR());
|
||||
}
|
||||
void CNullModem::setDTR(bool val) {
|
||||
setRTSDTR(getRTS(), val);
|
||||
}
|
||||
#endif
|
105
src/hardware/serialport/nullmodem.h
Normal file
105
src/hardware/serialport/nullmodem.h
Normal file
|
@ -0,0 +1,105 @@
|
|||
/*
|
||||
* Copyright (C) 2002-2007 The DOSBox Team
|
||||
*
|
||||
* 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
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
/* $Id: nullmodem.h,v 1.1 2007-01-13 08:35:49 qbix79 Exp $ */
|
||||
|
||||
// include guard
|
||||
#ifndef DOSBOX_NULLMODEM_WIN32_H
|
||||
#define DOSBOX_NULLMODEM_WIN32_H
|
||||
|
||||
#include "dosbox.h"
|
||||
|
||||
#if C_MODEM
|
||||
|
||||
#include "misc_util.h"
|
||||
#include "serialport.h"
|
||||
|
||||
#define SERIAL_SERVER_POLLING_EVENT SERIAL_BASE_EVENT_COUNT+1
|
||||
#define SERIAL_TX_REDUCTION SERIAL_BASE_EVENT_COUNT+2
|
||||
#define SERIAL_NULLMODEM_DTR_EVENT SERIAL_BASE_EVENT_COUNT+3
|
||||
#define SERIAL_NULLMODEM_EVENT_COUNT SERIAL_BASE_EVENT_COUNT+ 3
|
||||
|
||||
class CNullModem : public CSerial {
|
||||
public:
|
||||
TCPServerSocket* serversocket;
|
||||
TCPClientSocket* clientsocket;
|
||||
|
||||
CNullModem(Bitu id, CommandLine* cmd);
|
||||
~CNullModem();
|
||||
bool receiveblock; // It's not a block of data it rather blocks
|
||||
Bit16u serverport; // we are a server if this is nonzero
|
||||
Bit16u clientport;
|
||||
|
||||
Bit8u hostnamebuffer[128]; // the name passed to us by the user
|
||||
|
||||
void updatePortConfig(Bit16u divider, Bit8u lcr);
|
||||
void updateMSR();
|
||||
void transmitByte(Bit8u val, bool first);
|
||||
void setBreak(bool value);
|
||||
|
||||
void setRTSDTR(bool rts, bool dtr);
|
||||
void setRTS(bool val);
|
||||
void setDTR(bool val);
|
||||
void handleUpperEvent(Bit16u type);
|
||||
|
||||
void ClientConnect();
|
||||
void Disconnect();
|
||||
Bits readChar();
|
||||
void WriteChar(Bit8u data);
|
||||
|
||||
bool tx_block; // true while the SERIAL_TX_REDUCTION event
|
||||
// is pending
|
||||
|
||||
Bitu rx_retry; // counter of retries
|
||||
|
||||
Bitu rx_retry_max; // how many POLL_EVENTS to wait before causing
|
||||
// a overrun error.
|
||||
|
||||
Bitu tx_gather; // how long to gather tx data before
|
||||
// sending all of them [milliseconds]
|
||||
|
||||
|
||||
bool dtrrespect; // dtr behavior - only send data to the serial
|
||||
// port when DTR is on
|
||||
|
||||
bool transparent; // if true, don't send 0xff 0xXX to toggle
|
||||
// DSR/CTS.
|
||||
|
||||
bool telnet; // Do Telnet parsing.
|
||||
|
||||
// Telnet's brain
|
||||
#define TEL_CLIENT 0
|
||||
#define TEL_SERVER 1
|
||||
|
||||
Bits TelnetEmulation(Bit8u data);
|
||||
|
||||
// Telnet's memory
|
||||
struct {
|
||||
bool binary[2];
|
||||
bool echo[2];
|
||||
bool supressGA[2];
|
||||
bool timingMark[2];
|
||||
|
||||
bool inIAC;
|
||||
bool recCommand;
|
||||
Bit8u command;
|
||||
} telClient;
|
||||
};
|
||||
|
||||
#endif // C_MODEM
|
||||
#endif // include guard
|
|
@ -16,7 +16,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
/* $Id: serialdummy.cpp,v 1.3 2007-01-08 19:45:41 qbix79 Exp $ */
|
||||
/* $Id: serialdummy.cpp,v 1.4 2007-01-13 08:35:49 qbix79 Exp $ */
|
||||
|
||||
#include "dosbox.h"
|
||||
|
||||
|
@ -24,46 +24,54 @@
|
|||
#include "serialdummy.h"
|
||||
#include "serialport.h"
|
||||
|
||||
|
||||
CSerialDummy::CSerialDummy(
|
||||
IO_ReadHandler* rh,
|
||||
IO_WriteHandler* wh,
|
||||
TIMER_TickHandler th,
|
||||
Bit16u baseAddr,
|
||||
Bit8u initIrq,
|
||||
Bit32u initBps,
|
||||
Bit8u bytesize,
|
||||
const char* parity,
|
||||
Bit8u stopbits
|
||||
) : CSerial(
|
||||
rh, wh, th,
|
||||
baseAddr,initIrq,initBps,bytesize,parity,stopbits)
|
||||
{
|
||||
CSerial::Init_Registers(initBps,bytesize,parity,stopbits);
|
||||
}
|
||||
|
||||
CSerialDummy::~CSerialDummy() {
|
||||
CSerialDummy::CSerialDummy(Bitu id, CommandLine* cmd):CSerial(id, cmd) {
|
||||
CSerial::Init_Registers();
|
||||
setRI(false);
|
||||
setDSR(false);
|
||||
setCD(false);
|
||||
setCTS(false);
|
||||
InstallationSuccessful=true;
|
||||
}
|
||||
|
||||
void CSerialDummy::RXBufferEmpty() {
|
||||
// no external buffer, not used here
|
||||
CSerialDummy::~CSerialDummy() {
|
||||
// clear events
|
||||
removeEvent(SERIAL_TX_EVENT);
|
||||
}
|
||||
|
||||
void CSerialDummy::handleUpperEvent(Bit16u type) {
|
||||
if(type==SERIAL_TX_EVENT) {
|
||||
//LOG_MSG("SERIAL_TX_EVENT");
|
||||
#ifdef CHECKIT_TESTPLUG
|
||||
receiveByte(loopbackdata);
|
||||
#endif
|
||||
ByteTransmitted(); // tx timeout
|
||||
}
|
||||
else if(type==SERIAL_THR_EVENT){
|
||||
//LOG_MSG("SERIAL_THR_EVENT");
|
||||
ByteTransmitting();
|
||||
setEvent(SERIAL_TX_EVENT,bytetime);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/* updatePortConfig is called when emulated app changes the serial port **/
|
||||
/* parameters baudrate, stopbits, number of databits, parity. **/
|
||||
/*****************************************************************************/
|
||||
void CSerialDummy::updatePortConfig(Bit8u dll, Bit8u dlm, Bit8u lcr) {
|
||||
void CSerialDummy::updatePortConfig(Bit16u divider, Bit8u lcr) {
|
||||
//LOG_MSG("Serial port at 0x%x: Port params changed: %d Baud", base,dcb.BaudRate);
|
||||
}
|
||||
|
||||
void CSerialDummy::updateMSR() {
|
||||
changeMSR(0);
|
||||
}
|
||||
void CSerialDummy::transmitByte(Bit8u val, bool first) {
|
||||
|
||||
void CSerialDummy::transmitByte(Bit8u val) {
|
||||
ByteTransmitted();
|
||||
//LOG_MSG("UART 0x%x: TX 0x%x", base,val);
|
||||
if(first) setEvent(SERIAL_THR_EVENT, bytetime/10);
|
||||
else setEvent(SERIAL_TX_EVENT, bytetime);
|
||||
|
||||
#ifdef CHECKIT_TESTPLUG
|
||||
loopbackdata=val;
|
||||
#endif
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
@ -75,11 +83,21 @@ void CSerialDummy::setBreak(bool value) {
|
|||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/* updateModemControlLines(mcr) sets DTR and RTS. **/
|
||||
/* setRTSDTR sets the modem control lines **/
|
||||
/*****************************************************************************/
|
||||
void CSerialDummy::updateModemControlLines(/*Bit8u mcr*/) {
|
||||
void CSerialDummy::setRTSDTR(bool rts, bool dtr) {
|
||||
setRTS(rts);
|
||||
setDTR(dtr);
|
||||
}
|
||||
void CSerialDummy::setRTS(bool val) {
|
||||
#ifdef CHECKIT_TESTPLUG
|
||||
setCTS(val);
|
||||
#endif
|
||||
}
|
||||
void CSerialDummy::setDTR(bool val) {
|
||||
#ifdef CHECKIT_TESTPLUG
|
||||
setDSR(val);
|
||||
setRI(val);
|
||||
setCD(val);
|
||||
#endif
|
||||
}
|
||||
|
||||
void CSerialDummy::Timer2(void) {
|
||||
}
|
||||
|
||||
|
|
|
@ -16,39 +16,34 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
/* $Id: serialdummy.h,v 1.3 2007-01-08 19:45:41 qbix79 Exp $ */
|
||||
/* $Id: serialdummy.h,v 1.4 2007-01-13 08:35:49 qbix79 Exp $ */
|
||||
|
||||
#ifndef INCLUDEGUARD_SERIALDUMMY_H
|
||||
#define INCLUDEGUARD_SERIALDUMMY_H
|
||||
|
||||
#include "serialport.h"
|
||||
|
||||
//#define CHECKIT_TESTPLUG
|
||||
|
||||
class CSerialDummy : public CSerial {
|
||||
public:
|
||||
|
||||
CSerialDummy(
|
||||
IO_ReadHandler* rh,
|
||||
IO_WriteHandler* wh,
|
||||
TIMER_TickHandler th,
|
||||
Bit16u baseAddr,
|
||||
Bit8u initIrq,
|
||||
Bit32u initBps,
|
||||
Bit8u bytesize,
|
||||
const char* parity,
|
||||
Bit8u stopbits
|
||||
);
|
||||
|
||||
|
||||
CSerialDummy(Bitu id, CommandLine* cmd);
|
||||
~CSerialDummy();
|
||||
bool CanRecv(void);
|
||||
bool CanSend(void);
|
||||
void RXBufferEmpty();
|
||||
void updatePortConfig(Bit8u dll, Bit8u dlm, Bit8u lcr);
|
||||
|
||||
void setRTSDTR(bool rts, bool dtr);
|
||||
void setRTS(bool val);
|
||||
void setDTR(bool val);
|
||||
|
||||
void updatePortConfig(Bit16u, Bit8u lcr);
|
||||
void updateMSR();
|
||||
void transmitByte(Bit8u val);
|
||||
void transmitByte(Bit8u val, bool first);
|
||||
void setBreak(bool value);
|
||||
void updateModemControlLines(/*Bit8u mcr*/);
|
||||
void Timer2(void);
|
||||
void handleUpperEvent(Bit16u type);
|
||||
|
||||
#ifdef CHECKIT_TESTPLUG
|
||||
Bit8u loopbackdata;
|
||||
#endif
|
||||
|
||||
};
|
||||
|
||||
#endif // INCLUDEGUARD
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -16,7 +16,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
/* $Id: softmodem.cpp,v 1.6 2007-01-08 19:45:41 qbix79 Exp $ */
|
||||
/* $Id: softmodem.cpp,v 1.7 2007-01-13 08:35:49 qbix79 Exp $ */
|
||||
|
||||
#include "dosbox.h"
|
||||
|
||||
|
@ -26,90 +26,88 @@
|
|||
#include <stdlib.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#include "SDL_net.h"
|
||||
|
||||
#include "support.h"
|
||||
#include "timer.h"
|
||||
#include "serialport.h"
|
||||
#include "softmodem.h"
|
||||
#include "misc_util.h"
|
||||
|
||||
//#include "mixer.h"
|
||||
|
||||
|
||||
CSerialModem::CSerialModem(
|
||||
IO_ReadHandler* rh,
|
||||
IO_WriteHandler* wh,
|
||||
TIMER_TickHandler th,
|
||||
Bit16u baseAddr,
|
||||
Bit8u initIrq,
|
||||
Bit32u initBps,
|
||||
Bit8u bytesize,
|
||||
const char* parity,
|
||||
Bit8u stopbits,
|
||||
const char *remotestr,
|
||||
Bit16u lport)
|
||||
: CSerial(rh, wh, th,
|
||||
baseAddr, initIrq, initBps, bytesize, parity, stopbits) {
|
||||
socket=0;
|
||||
incomingsocket=0;
|
||||
InstallTimerHandler(th);
|
||||
CSerialModem::CSerialModem(Bitu id, CommandLine* cmd):CSerial(id, cmd) {
|
||||
InstallationSuccessful=false;
|
||||
connected=false;
|
||||
|
||||
if(!SDLNetInited) {
|
||||
if(SDLNet_Init()==-1) {
|
||||
LOG_MSG("SDLNet_Init failed: %s\n", SDLNet_GetError());
|
||||
return;
|
||||
}
|
||||
SDLNetInited = true;
|
||||
}
|
||||
rqueue=new CFifo(MODEM_BUFFER_QUEUE_SIZE);
|
||||
tqueue=new CFifo(MODEM_BUFFER_QUEUE_SIZE);
|
||||
|
||||
/* Default to direct null modem connection. Telnet mode interprets IAC codes */
|
||||
// Default to direct null modem connection. Telnet mode interprets IAC codes
|
||||
telnetmode = false;
|
||||
|
||||
/* Initialize the sockets and setup the listening port */
|
||||
socketset = SDLNet_AllocSocketSet(1);
|
||||
listensocketset = SDLNet_AllocSocketSet(1);
|
||||
if (!socketset || !listensocketset) {
|
||||
LOG_MSG("MODEM:Can't open socketset:%s",SDLNet_GetError());
|
||||
//TODO Should probably just exit
|
||||
return;
|
||||
}
|
||||
socket=0;
|
||||
listenport=lport;
|
||||
if (listenport) {
|
||||
IPaddress listen_ip;
|
||||
SDLNet_ResolveHost(&listen_ip, NULL, listenport);
|
||||
listensocket=SDLNet_TCP_Open(&listen_ip);
|
||||
if (!listensocket) LOG_MSG("MODEM:Can't open listen port: %s",SDLNet_GetError());
|
||||
|
||||
else LOG_MSG("MODEM: Port listener installed at port %d",listenport);
|
||||
|
||||
}
|
||||
else listensocket=0;
|
||||
|
||||
// TODO: Fix dialtones if requested
|
||||
//mhd.chan=MIXER_AddChannel((MIXER_MixHandler)this->MODEM_CallBack,8000,"MODEM");
|
||||
//MIXER_Enable(mhd.chan,false);
|
||||
//MIXER_SetMode(mhd.chan,MIXER_16MONO);
|
||||
// Initialize the sockets and setup the listening port
|
||||
listenport = 23;
|
||||
waitingclientsocket=0;
|
||||
clientsocket = 0;
|
||||
serversocket = 0;
|
||||
getBituSubstring("listenport:", &listenport, cmd);
|
||||
|
||||
// TODO: Fix dialtones if requested
|
||||
//mhd.chan=MIXER_AddChannel((MIXER_MixHandler)this->MODEM_CallBack,8000,"MODEM");
|
||||
//MIXER_Enable(mhd.chan,false);
|
||||
//MIXER_SetMode(mhd.chan,MIXER_16MONO);
|
||||
|
||||
Reset();
|
||||
//EnterIdleState();
|
||||
CSerial::Init_Registers(initBps,bytesize,parity,stopbits);
|
||||
}
|
||||
CSerial::Init_Registers();
|
||||
Reset(); // reset calls EnterIdleState
|
||||
|
||||
setEvent(SERIAL_POLLING_EVENT,1);
|
||||
InstallationSuccessful=true;
|
||||
}
|
||||
|
||||
CSerialModem::~CSerialModem() {
|
||||
if(socket) {
|
||||
SDLNet_TCP_DelSocket(socketset,socket);
|
||||
SDLNet_TCP_Close(socket);
|
||||
CSerialModem::~CSerialModem() {
|
||||
if(serversocket) delete serversocket;
|
||||
if(clientsocket) delete clientsocket;
|
||||
if(waitingclientsocket) delete waitingclientsocket;
|
||||
|
||||
delete rqueue;
|
||||
delete tqueue;
|
||||
|
||||
// remove events
|
||||
for(Bitu i = SERIAL_BASE_EVENT_COUNT+1; i <= SERIAL_MODEM_EVENT_COUNT; i++)
|
||||
removeEvent(i);
|
||||
}
|
||||
|
||||
void CSerialModem::handleUpperEvent(Bit16u type) {
|
||||
switch(type)
|
||||
{
|
||||
case SERIAL_RX_EVENT:
|
||||
{
|
||||
break;
|
||||
}
|
||||
case MODEM_TX_EVENT:
|
||||
{
|
||||
if(tqueue->left()) {
|
||||
tqueue->addb(waiting_tx_character);
|
||||
if(tqueue->left() < 2) {
|
||||
CSerial::setCTS(false);
|
||||
}
|
||||
} else LOG_MSG("MODEM: TX Buffer overflow!");
|
||||
ByteTransmitted();
|
||||
|
||||
break;
|
||||
}
|
||||
case SERIAL_POLLING_EVENT:
|
||||
{
|
||||
Timer2();
|
||||
setEvent(SERIAL_POLLING_EVENT,1);
|
||||
break;
|
||||
}
|
||||
|
||||
if(listensocket) SDLNet_TCP_Close(listensocket);
|
||||
if(socketset) SDLNet_FreeSocketSet(socketset);
|
||||
|
||||
delete rqueue;
|
||||
delete tqueue;
|
||||
case MODEM_RING_EVENT:
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CSerialModem::SendLine(const char *line) {
|
||||
rqueue->addb(0xd);
|
||||
|
@ -164,18 +162,9 @@ void CSerialModem::SendRes(ResTypes response) {
|
|||
}
|
||||
}
|
||||
|
||||
void CSerialModem::openConnection(void) {
|
||||
if (socket) {
|
||||
LOG_MSG("Huh? already connected");
|
||||
SDLNet_TCP_DelSocket(socketset,socket);
|
||||
SDLNet_TCP_Close(socket);
|
||||
}
|
||||
socket = SDLNet_TCP_Open(&openip);
|
||||
}
|
||||
|
||||
bool CSerialModem::Dial(char * host) {
|
||||
|
||||
/* Scan host for port */
|
||||
// Scan host for port
|
||||
Bit16u port;
|
||||
char * hasport=strrchr(host,':');
|
||||
if (hasport) {
|
||||
|
@ -183,26 +172,30 @@ bool CSerialModem::Dial(char * host) {
|
|||
port=(Bit16u)atoi(hasport);
|
||||
}
|
||||
else port=MODEM_DEFAULT_PORT;
|
||||
/* Resolve host we're gonna dial */
|
||||
// Resolve host we're gonna dial
|
||||
LOG_MSG("Connecting to host %s port %d",host,port);
|
||||
if (!SDLNet_ResolveHost(&openip,host,port)) {
|
||||
openConnection();
|
||||
EnterConnectedState();
|
||||
return true;
|
||||
} else {
|
||||
LOG_MSG("Failed to resolve host %s: %s",host,SDLNet_GetError());
|
||||
SendRes(ResNODIALTONE);
|
||||
clientsocket = new TCPClientSocket(host, port);
|
||||
if(!clientsocket->isopen) {
|
||||
delete clientsocket;
|
||||
clientsocket=0;
|
||||
LOG_MSG("Failed to connect.");
|
||||
SendRes(ResNOCARRIER);
|
||||
EnterIdleState();
|
||||
return false;
|
||||
} else {
|
||||
EnterConnectedState();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
void CSerialModem::AcceptIncomingCall(void) {
|
||||
// assert(!socket);
|
||||
socket=incomingsocket;
|
||||
SDLNet_TCP_AddSocket(socketset,socket);
|
||||
incomingsocket = 0;
|
||||
EnterConnectedState();
|
||||
if(waitingclientsocket) {
|
||||
clientsocket=waitingclientsocket;
|
||||
waitingclientsocket=0;
|
||||
EnterConnectedState();
|
||||
} else {
|
||||
EnterIdleState();
|
||||
}
|
||||
}
|
||||
|
||||
Bitu CSerialModem::ScanNumber(char * & scan) {
|
||||
|
@ -224,7 +217,10 @@ void CSerialModem::Reset(){
|
|||
oldDTRstate = getDTR();
|
||||
flowcontrol = 0;
|
||||
plusinc = 0;
|
||||
incomingsocket = 0;
|
||||
if(clientsocket) {
|
||||
delete clientsocket;
|
||||
clientsocket=0;
|
||||
}
|
||||
memset(®,0,sizeof(reg));
|
||||
reg[MREG_AUTOANSWER_COUNT]=0; // no autoanswer
|
||||
reg[MREG_RING_COUNT] = 1;
|
||||
|
@ -246,23 +242,29 @@ void CSerialModem::EnterIdleState(void){
|
|||
connected=false;
|
||||
ringing=false;
|
||||
|
||||
if(socket) { // clear current socket
|
||||
SDLNet_TCP_DelSocket(socketset,socket);
|
||||
SDLNet_TCP_Close(socket);
|
||||
socket=0;
|
||||
if(clientsocket) {
|
||||
delete clientsocket;
|
||||
clientsocket=0;
|
||||
}
|
||||
if(incomingsocket) { // clear current incoming socket
|
||||
SDLNet_TCP_DelSocket(socketset,incomingsocket);
|
||||
SDLNet_TCP_Close(incomingsocket);
|
||||
|
||||
if(waitingclientsocket) { // clear current incoming socket
|
||||
delete waitingclientsocket;
|
||||
waitingclientsocket=0;
|
||||
}
|
||||
// get rid of everything
|
||||
if(listensocket) {
|
||||
while(incomingsocket=SDLNet_TCP_Accept(listensocket)) {
|
||||
SDLNet_TCP_DelSocket(socketset,incomingsocket);
|
||||
SDLNet_TCP_Close(incomingsocket);
|
||||
}
|
||||
if(serversocket) {
|
||||
while(waitingclientsocket=serversocket->Accept())
|
||||
delete waitingclientsocket;
|
||||
} else if (listenport) {
|
||||
|
||||
serversocket=new TCPServerSocket(listenport);
|
||||
if(!serversocket->isopen) {
|
||||
LOG_MSG("Serial%d: Modem could not open TCP port %d.",COMNUMBER,listenport);
|
||||
delete serversocket;
|
||||
serversocket=0;
|
||||
} else LOG_MSG("Serial%d: Modem listening on port %d...",COMNUMBER,listenport);
|
||||
}
|
||||
incomingsocket=0;
|
||||
waitingclientsocket=0;
|
||||
|
||||
commandmode = true;
|
||||
CSerial::setCD(false);
|
||||
|
@ -273,19 +275,18 @@ void CSerialModem::EnterIdleState(void){
|
|||
}
|
||||
|
||||
void CSerialModem::EnterConnectedState(void) {
|
||||
if(socket) {
|
||||
SDLNet_TCP_AddSocket(socketset,socket);
|
||||
SendRes(ResCONNECT);
|
||||
commandmode = false;
|
||||
memset(&telClient, 0, sizeof(telClient));
|
||||
connected = true;
|
||||
ringing = false;
|
||||
CSerial::setCD(true);
|
||||
CSerial::setRI(false);
|
||||
} else {
|
||||
SendRes(ResNOCARRIER);
|
||||
EnterIdleState();
|
||||
if(serversocket) {
|
||||
// we don't accept further calls
|
||||
delete serversocket;
|
||||
serversocket=0;
|
||||
}
|
||||
SendRes(ResCONNECT);
|
||||
commandmode = false;
|
||||
memset(&telClient, 0, sizeof(telClient));
|
||||
connected = true;
|
||||
ringing = false;
|
||||
CSerial::setCD(true);
|
||||
CSerial::setRI(false);
|
||||
}
|
||||
|
||||
void CSerialModem::DoCommand() {
|
||||
|
@ -309,7 +310,7 @@ void CSerialModem::DoCommand() {
|
|||
|
||||
if ((cmdbuf[0] != 'A') || (cmdbuf[1] != 'T')) {
|
||||
SendRes(ResERROR);
|
||||
return;//goto ret_error;
|
||||
return;
|
||||
}
|
||||
|
||||
if (strstr(cmdbuf,"NET0")) {
|
||||
|
@ -329,7 +330,7 @@ void CSerialModem::DoCommand() {
|
|||
if (*foundstr=='T' || *foundstr=='P') foundstr++;
|
||||
/* Small protection against empty line */
|
||||
if (!foundstr[0]) {
|
||||
SendRes(ResERROR);//goto ret_error;
|
||||
SendRes(ResERROR);
|
||||
return;
|
||||
}
|
||||
char* helper;
|
||||
|
@ -397,7 +398,7 @@ void CSerialModem::DoCommand() {
|
|||
if (connected) {
|
||||
SendRes(ResNOCARRIER);
|
||||
EnterIdleState();
|
||||
return;//goto ret_none;
|
||||
return;
|
||||
}
|
||||
//Else return ok
|
||||
};break;
|
||||
|
@ -405,12 +406,12 @@ void CSerialModem::DoCommand() {
|
|||
switch (num=ScanNumber(scanbuf))
|
||||
{
|
||||
case 0:
|
||||
if (socket) {
|
||||
if (clientsocket) {
|
||||
commandmode = false;
|
||||
return;//goto ret_none;
|
||||
return;
|
||||
} else {
|
||||
SendRes(ResERROR);
|
||||
return;//goto ret_none;
|
||||
return;
|
||||
}
|
||||
};break;
|
||||
case 'T': //Tone Dial
|
||||
|
@ -421,18 +422,18 @@ void CSerialModem::DoCommand() {
|
|||
ScanNumber(scanbuf);
|
||||
break;
|
||||
case 'A': //Answer call
|
||||
if (incomingsocket) {
|
||||
if (waitingclientsocket) {
|
||||
AcceptIncomingCall();
|
||||
} else {
|
||||
SendRes(ResERROR);
|
||||
return;//goto ret_none;
|
||||
return;
|
||||
}
|
||||
return;//goto ret_none;
|
||||
return;
|
||||
case 'Z': //Reset and load profiles
|
||||
{
|
||||
// scan the number away, if any
|
||||
ScanNumber(scanbuf);
|
||||
if (socket) SendRes(ResNOCARRIER);
|
||||
if (clientsocket/*socket*/) SendRes(ResNOCARRIER);
|
||||
Reset();
|
||||
break;
|
||||
}
|
||||
|
@ -525,107 +526,103 @@ void CSerialModem::TelnetEmulation(Bit8u * data, Bitu size) {
|
|||
LOG_MSG("MODEM: Unrecognized option %d", c);
|
||||
if(telClient.command>250) {
|
||||
/* Reject anything we don't recognize */
|
||||
tqueue->addb(0xff);
|
||||
tqueue->addb(252);
|
||||
tqueue->addb(c); /* We won't do crap! */
|
||||
}
|
||||
}
|
||||
switch(telClient.command) {
|
||||
case 251: /* Will */
|
||||
if(c == 0) telClient.binary[TEL_SERVER] = true;
|
||||
if(c == 1) telClient.echo[TEL_SERVER] = true;
|
||||
if(c == 3) telClient.supressGA[TEL_SERVER] = true;
|
||||
break;
|
||||
case 252: /* Won't */
|
||||
if(c == 0) telClient.binary[TEL_SERVER] = false;
|
||||
if(c == 1) telClient.echo[TEL_SERVER] = false;
|
||||
if(c == 3) telClient.supressGA[TEL_SERVER] = false;
|
||||
break;
|
||||
case 253: /* Do */
|
||||
if(c == 0) {
|
||||
telClient.binary[TEL_CLIENT] = true;
|
||||
tqueue->addb(0xff);
|
||||
tqueue->addb(251);
|
||||
tqueue->addb(0); /* Will do binary transfer */
|
||||
}
|
||||
if(c == 1) {
|
||||
telClient.echo[TEL_CLIENT] = false;
|
||||
tqueue->addb(0xff);
|
||||
tqueue->addb(252);
|
||||
tqueue->addb(c); /* We won't do crap! */
|
||||
tqueue->addb(1); /* Won't echo (too lazy) */
|
||||
}
|
||||
}
|
||||
switch(telClient.command) {
|
||||
case 251: /* Will */
|
||||
if(c == 0) telClient.binary[TEL_SERVER] = true;
|
||||
if(c == 1) telClient.echo[TEL_SERVER] = true;
|
||||
if(c == 3) telClient.supressGA[TEL_SERVER] = true;
|
||||
break;
|
||||
case 252: /* Won't */
|
||||
if(c == 0) telClient.binary[TEL_SERVER] = false;
|
||||
if(c == 1) telClient.echo[TEL_SERVER] = false;
|
||||
if(c == 3) telClient.supressGA[TEL_SERVER] = false;
|
||||
break;
|
||||
case 253: /* Do */
|
||||
if(c == 0) {
|
||||
telClient.binary[TEL_CLIENT] = true;
|
||||
tqueue->addb(0xff);
|
||||
tqueue->addb(251);
|
||||
tqueue->addb(0); /* Will do binary transfer */
|
||||
}
|
||||
if(c == 1) {
|
||||
telClient.echo[TEL_CLIENT] = false;
|
||||
tqueue->addb(0xff);
|
||||
tqueue->addb(252);
|
||||
tqueue->addb(1); /* Won't echo (too lazy) */
|
||||
}
|
||||
if(c == 3) {
|
||||
telClient.supressGA[TEL_CLIENT] = true;
|
||||
tqueue->addb(0xff);
|
||||
tqueue->addb(251);
|
||||
tqueue->addb(3); /* Will Suppress GA */
|
||||
}
|
||||
break;
|
||||
case 254: /* Don't */
|
||||
if(c == 0) {
|
||||
telClient.binary[TEL_CLIENT] = false;
|
||||
tqueue->addb(0xff);
|
||||
tqueue->addb(252);
|
||||
tqueue->addb(0); /* Won't do binary transfer */
|
||||
}
|
||||
if(c == 1) {
|
||||
telClient.echo[TEL_CLIENT] = false;
|
||||
tqueue->addb(0xff);
|
||||
tqueue->addb(252);
|
||||
tqueue->addb(1); /* Won't echo (fine by me) */
|
||||
}
|
||||
if(c == 3) {
|
||||
telClient.supressGA[TEL_CLIENT] = true;
|
||||
tqueue->addb(0xff);
|
||||
tqueue->addb(251);
|
||||
tqueue->addb(3); /* Will Suppress GA (too lazy) */
|
||||
}
|
||||
break;
|
||||
default:
|
||||
LOG_MSG("MODEM: Telnet client sent IAC %d", telClient.command);
|
||||
break;
|
||||
}
|
||||
|
||||
if(c == 3) {
|
||||
telClient.supressGA[TEL_CLIENT] = true;
|
||||
tqueue->addb(0xff);
|
||||
tqueue->addb(251);
|
||||
tqueue->addb(3); /* Will Suppress GA */
|
||||
}
|
||||
break;
|
||||
case 254: /* Don't */
|
||||
if(c == 0) {
|
||||
telClient.binary[TEL_CLIENT] = false;
|
||||
tqueue->addb(0xff);
|
||||
tqueue->addb(252);
|
||||
tqueue->addb(0); /* Won't do binary transfer */
|
||||
}
|
||||
if(c == 1) {
|
||||
telClient.echo[TEL_CLIENT] = false;
|
||||
tqueue->addb(0xff);
|
||||
tqueue->addb(252);
|
||||
tqueue->addb(1); /* Won't echo (fine by me) */
|
||||
}
|
||||
if(c == 3) {
|
||||
telClient.supressGA[TEL_CLIENT] = true;
|
||||
tqueue->addb(0xff);
|
||||
tqueue->addb(251);
|
||||
tqueue->addb(3); /* Will Suppress GA (too lazy) */
|
||||
}
|
||||
break;
|
||||
default:
|
||||
LOG_MSG("MODEM: Telnet client sent IAC %d", telClient.command);
|
||||
break;
|
||||
}
|
||||
telClient.inIAC = false;
|
||||
telClient.recCommand = false;
|
||||
continue;
|
||||
} else {
|
||||
if(c==249) {
|
||||
/* Go Ahead received */
|
||||
telClient.inIAC = false;
|
||||
continue;
|
||||
}
|
||||
telClient.command = c;
|
||||
telClient.recCommand = true;
|
||||
|
||||
if((telClient.binary[TEL_SERVER]) && (c == 0xff)) {
|
||||
/* Binary data with value of 255 */
|
||||
telClient.inIAC = false;
|
||||
telClient.recCommand = false;
|
||||
rqueue->addb(0xff);
|
||||
continue;
|
||||
|
||||
} else {
|
||||
if(c==249) {
|
||||
/* Go Ahead received */
|
||||
telClient.inIAC = false;
|
||||
continue;
|
||||
}
|
||||
telClient.command = c;
|
||||
telClient.recCommand = true;
|
||||
|
||||
if((telClient.binary[TEL_SERVER]) && (c == 0xff)) {
|
||||
/* Binary data with value of 255 */
|
||||
telClient.inIAC = false;
|
||||
telClient.recCommand = false;
|
||||
rqueue->addb(0xff);
|
||||
continue;
|
||||
}
|
||||
|
||||
}
|
||||
} else {
|
||||
if(c == 0xff) {
|
||||
telClient.inIAC = true;
|
||||
continue;
|
||||
}
|
||||
rqueue->addb(c);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if(c == 0xff) {
|
||||
telClient.inIAC = true;
|
||||
continue;
|
||||
}
|
||||
rqueue->addb(c);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CSerialModem::Timer2(void) {
|
||||
int result =0;
|
||||
|
||||
unsigned long args = 1;
|
||||
bool sendbyte = true;
|
||||
Bitu usesize;
|
||||
Bit8u txval;
|
||||
Bitu txbuffersize =0;
|
||||
Bitu testres = 0;
|
||||
|
||||
// check for bytes to be sent to port
|
||||
if(CSerial::CanReceiveByte())
|
||||
|
@ -634,13 +631,11 @@ void CSerialModem::Timer2(void) {
|
|||
//LOG_MSG("Modem: sending byte %2x back to UART3",rbyte);
|
||||
CSerial::receiveByte(rbyte);
|
||||
}
|
||||
/* Check for eventual break command */
|
||||
// Check for eventual break command
|
||||
if (!commandmode) cmdpause++;
|
||||
/* Handle incoming data from serial port, read as much as available */
|
||||
//Bitu tx_size=tqueue->inuse();
|
||||
//Bitu tx_first = tx_size; // TODO:comment out
|
||||
// Handle incoming data from serial port, read as much as available
|
||||
CSerial::setCTS(true); // buffer will get 'emptier', new data can be received
|
||||
while (/*tx_size--*/tqueue->inuse()) {
|
||||
while (tqueue->inuse()) {
|
||||
txval = tqueue->getb();
|
||||
if (commandmode) {
|
||||
if (echo) {
|
||||
|
@ -658,9 +653,9 @@ void CSerialModem::Timer2(void) {
|
|||
}
|
||||
}
|
||||
else {// + character
|
||||
/* 1000 ticks have passed, can check for pause command */
|
||||
// 1000 ticks have passed, can check for pause command
|
||||
if (cmdpause > 1000) {
|
||||
if(txval ==/* '+')*/reg[MREG_ESCAPE_CHAR])
|
||||
if(txval ==reg[MREG_ESCAPE_CHAR]) // +
|
||||
{
|
||||
plusinc++;
|
||||
if(plusinc>=3) {
|
||||
|
@ -673,46 +668,37 @@ void CSerialModem::Timer2(void) {
|
|||
} else {
|
||||
plusinc=0;
|
||||
}
|
||||
//If not a special pause command, should go for bigger blocks to send
|
||||
// If not a special pause command, should go for bigger blocks to send
|
||||
}
|
||||
tmpbuf[txbuffersize] = txval;
|
||||
txbuffersize++;
|
||||
}
|
||||
} // while loop
|
||||
|
||||
if (socket && sendbyte && txbuffersize) {
|
||||
if (clientsocket && sendbyte && txbuffersize) {
|
||||
// down here it saves a lot of network traffic
|
||||
SDLNet_TCP_Send(socket, tmpbuf,txbuffersize);
|
||||
clientsocket->SendArray(tmpbuf,txbuffersize);
|
||||
//TODO error testing
|
||||
}
|
||||
SDLNet_CheckSockets(socketset,0);
|
||||
/* Handle incoming to the serial port */
|
||||
if(!commandmode && socket) {
|
||||
if(rqueue->left() && SDLNet_SocketReady(socket) /*&& CSerial::getRTS()*/)
|
||||
{
|
||||
usesize = rqueue->left();
|
||||
if (usesize>16) usesize=16;
|
||||
result = SDLNet_TCP_Recv(socket, tmpbuf, usesize);
|
||||
if (result>0) {
|
||||
if(telnetmode) {
|
||||
/* Filter telnet commands */
|
||||
TelnetEmulation(tmpbuf, result);
|
||||
} else {
|
||||
rqueue->adds(tmpbuf,result);
|
||||
}
|
||||
cmdpause = 0;
|
||||
} else {
|
||||
SendRes(ResNOCARRIER);
|
||||
EnterIdleState();
|
||||
}
|
||||
}
|
||||
// Handle incoming to the serial port
|
||||
if(!commandmode && clientsocket && rqueue->left()) {
|
||||
usesize = rqueue->left();
|
||||
if (usesize>16) usesize=16;
|
||||
if(!clientsocket->ReceiveArray(tmpbuf, &usesize)) {
|
||||
SendRes(ResNOCARRIER);
|
||||
EnterIdleState();
|
||||
} else if(usesize) {
|
||||
// LOG_MSG("rcv:%d", result);
|
||||
// Filter telnet commands
|
||||
if(telnetmode) TelnetEmulation(tmpbuf, usesize);
|
||||
else rqueue->adds(tmpbuf,usesize);
|
||||
cmdpause = 0;
|
||||
}
|
||||
}
|
||||
/* Check for incoming calls */
|
||||
if (!connected && !incomingsocket && listensocket) {
|
||||
incomingsocket = SDLNet_TCP_Accept(listensocket);
|
||||
if (incomingsocket) {
|
||||
SDLNet_TCP_AddSocket(listensocketset, incomingsocket);
|
||||
|
||||
// Check for incoming calls
|
||||
if (!connected && !waitingclientsocket && serversocket) {
|
||||
waitingclientsocket=serversocket->Accept();
|
||||
if(waitingclientsocket) {
|
||||
if(!CSerial::getDTR()) {
|
||||
// accept no calls with DTR off; TODO: AT &Dn
|
||||
EnterIdleState();
|
||||
|
@ -754,18 +740,14 @@ void CSerialModem::RXBufferEmpty() {
|
|||
}
|
||||
}
|
||||
|
||||
void CSerialModem::transmitByte(Bit8u val) {
|
||||
void CSerialModem::transmitByte(Bit8u val, bool first) {
|
||||
waiting_tx_character=val;
|
||||
setEvent(MODEM_TX_EVENT, bytetime); // TX event
|
||||
if(first) ByteTransmitting();
|
||||
//LOG_MSG("MODEM: Byte %x to be transmitted",val);
|
||||
if(tqueue->left()) {
|
||||
tqueue->addb(val);
|
||||
if(tqueue->left() < 2) {
|
||||
CSerial::setCTS(false);
|
||||
}
|
||||
} else LOG_MSG("MODEM: TX Buffer overflow!");
|
||||
CSerial::ByteTransmitted();
|
||||
}
|
||||
|
||||
void CSerialModem::updatePortConfig(Bit8u dll, Bit8u dlm, Bit8u lcr) {
|
||||
void CSerialModem::updatePortConfig(Bit16u, Bit8u lcr) {
|
||||
// nothing to do here right?
|
||||
}
|
||||
|
||||
|
@ -777,6 +759,21 @@ void CSerialModem::setBreak(bool) {
|
|||
// TODO: handle this
|
||||
}
|
||||
|
||||
void CSerialModem::setRTSDTR(bool rts, bool dtr) {
|
||||
setDTR(dtr);
|
||||
}
|
||||
void CSerialModem::setRTS(bool val) {
|
||||
|
||||
}
|
||||
void CSerialModem::setDTR(bool val) {
|
||||
if(!val && connected) {
|
||||
// If DTR goes low, hang up.
|
||||
SendRes(ResNOCARRIER);
|
||||
EnterIdleState();
|
||||
LOG_MSG("Modem: Hang up due to dropped DTR.");
|
||||
}
|
||||
}
|
||||
/*
|
||||
void CSerialModem::updateModemControlLines() {
|
||||
//bool txrdy=tqueue->left();
|
||||
//if(CSerial::getRTS() && txrdy) CSerial::setCTS(true);
|
||||
|
@ -793,7 +790,7 @@ void CSerialModem::updateModemControlLines() {
|
|||
|
||||
oldDTRstate = getDTR();
|
||||
}
|
||||
|
||||
*/
|
||||
|
||||
#endif
|
||||
|
||||
|
|
|
@ -16,16 +16,17 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
/* $Id: softmodem.h,v 1.6 2007-01-08 19:45:41 qbix79 Exp $ */
|
||||
/* $Id: softmodem.h,v 1.7 2007-01-13 08:35:49 qbix79 Exp $ */
|
||||
|
||||
#ifndef DOSBOX_SERIALMODEM_H
|
||||
#define DOSBOX_SERIALMODEM_H
|
||||
|
||||
#include "dosbox.h"
|
||||
#if C_MODEM
|
||||
#include "SDL_net.h"
|
||||
#include "serialport.h"
|
||||
|
||||
#include "misc_util.h"
|
||||
|
||||
#define MODEMSPD 57600
|
||||
#define SREGS 100
|
||||
|
||||
|
@ -34,6 +35,12 @@
|
|||
|
||||
#define MODEM_DEFAULT_PORT 23
|
||||
|
||||
#define MODEM_TX_EVENT SERIAL_BASE_EVENT_COUNT + 1
|
||||
#define MODEM_RX_POLLING SERIAL_BASE_EVENT_COUNT + 2
|
||||
#define MODEM_RING_EVENT SERIAL_BASE_EVENT_COUNT + 3
|
||||
#define SERIAL_MODEM_EVENT_COUNT SERIAL_BASE_EVENT_COUNT+3
|
||||
|
||||
|
||||
enum ResTypes {
|
||||
ResNONE,
|
||||
ResOK,ResERROR,
|
||||
|
@ -118,9 +125,6 @@ public:
|
|||
private:
|
||||
Bit8u * data;
|
||||
Bitu size,pos,used;
|
||||
//Bit8u tmpbuf[MODEM_BUFFER_QUEUE_SIZE];
|
||||
|
||||
|
||||
};
|
||||
#define MREG_AUTOANSWER_COUNT 0
|
||||
#define MREG_RING_COUNT 1
|
||||
|
@ -136,20 +140,7 @@ public:
|
|||
CFifo *rqueue;
|
||||
CFifo *tqueue;
|
||||
|
||||
CSerialModem(
|
||||
IO_ReadHandler* rh,
|
||||
IO_WriteHandler* wh,
|
||||
TIMER_TickHandler th,
|
||||
Bit16u baseAddr,
|
||||
Bit8u initIrq,
|
||||
Bit32u initBps,
|
||||
Bit8u bytesize,
|
||||
const char* parity,
|
||||
Bit8u stopbits,
|
||||
|
||||
const char *remotestr = NULL,
|
||||
Bit16u lport = 23);
|
||||
|
||||
CSerialModem(Bitu id, CommandLine* cmd);
|
||||
~CSerialModem();
|
||||
|
||||
void Reset();
|
||||
|
@ -172,17 +163,21 @@ public:
|
|||
|
||||
void TelnetEmulation(Bit8u * data, Bitu size);
|
||||
|
||||
//TODO
|
||||
void Timer2(void);
|
||||
void handleUpperEvent(Bit16u type);
|
||||
|
||||
void RXBufferEmpty();
|
||||
|
||||
void transmitByte(Bit8u val);
|
||||
void updatePortConfig(Bit8u dll, Bit8u dlm, Bit8u lcr);
|
||||
void transmitByte(Bit8u val, bool first);
|
||||
void updatePortConfig(Bit16u divider, Bit8u lcr);
|
||||
void updateMSR();
|
||||
|
||||
void setBreak(bool);
|
||||
|
||||
void updateModemControlLines(/*Bit8u mcr*/);
|
||||
void setRTSDTR(bool rts, bool dtr);
|
||||
void setRTS(bool val);
|
||||
void setDTR(bool val);
|
||||
|
||||
protected:
|
||||
char cmdbuf[255];
|
||||
|
@ -199,7 +194,7 @@ protected:
|
|||
bool connected;
|
||||
Bitu doresponse;
|
||||
|
||||
|
||||
Bit8u waiting_tx_character;
|
||||
|
||||
Bitu cmdpause;
|
||||
Bits ringtimer;
|
||||
|
@ -208,18 +203,15 @@ protected:
|
|||
Bitu cmdpos;
|
||||
Bitu flowcontrol;
|
||||
|
||||
//Bit8u mctrl;
|
||||
Bit8u tmpbuf[MODEM_BUFFER_QUEUE_SIZE];
|
||||
|
||||
Bitu listenport;
|
||||
Bit8u reg[SREGS];
|
||||
IPaddress openip;
|
||||
TCPsocket incomingsocket;
|
||||
TCPsocket socket;
|
||||
|
||||
TCPsocket listensocket;
|
||||
SDLNet_SocketSet socketset;
|
||||
SDLNet_SocketSet listensocketset;
|
||||
|
||||
TCPServerSocket* serversocket;
|
||||
TCPClientSocket* clientsocket;
|
||||
TCPClientSocket* waitingclientsocket;
|
||||
|
||||
struct {
|
||||
bool binary[2];
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue