CSerialModem::CSerialModem(Bitu id, CommandLine* cmd):CSerial(id, cmd) { InstallationSuccessful=false; connected=false; 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 telnetmode = false; // 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); CSerial::Init_Registers(); Reset(); // reset calls EnterIdleState setEvent(SERIAL_POLLING_EVENT,1); InstallationSuccessful=true; }
CDirectSerial::CDirectSerial (Bitu id, CommandLine* cmd) :CSerial (id, cmd) { InstallationSuccessful = false; comport = 0; rx_retry = 0; rx_retry_max = 0; std::string tmpstring; if(!cmd->FindStringBegin("realport:",tmpstring,false)) return; LOG_MSG ("Serial%d: Opening %s", COMNUMBER, tmpstring.c_str()); if(!SERIAL_open(tmpstring.c_str(), &comport)) { char errorbuffer[256]; SERIAL_getErrorString(errorbuffer, sizeof(errorbuffer)); LOG_MSG("Serial%d: Serial Port \"%s\" could not be opened.", COMNUMBER, tmpstring.c_str()); LOG_MSG("%s",errorbuffer); return; } #if SERIAL_DEBUG dbgmsg_poll_block=false; dbgmsg_rx_block=false; #endif // 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; } } CSerial::Init_Registers(); InstallationSuccessful = true; rx_state = D_RX_IDLE; setEvent(SERIAL_POLLING_EVENT, 1); // millisecond receive tick }
CDirectSerial::CDirectSerial (Bitu id, CommandLine* cmd) :CSerial (id, cmd) { InstallationSuccessful = false; hCom = INVALID_HANDLE_VALUE; // else destructor may close an invalid handle 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 NULL // hTemplate must be NULL for comm devices ); if (hCom == INVALID_HANDLE_VALUE) { int error = GetLastError (); 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) { LOG_MSG ("The specified port is already in use."); } else { LOG_MSG ("Windows error %d occurred.", error); } return; } dcb.DCBlength=sizeof(dcb); fSuccess = GetCommState (hCom, &dcb); if (!fSuccess) { // Handle the error. LOG_MSG ("GetCommState failed with error %d.\n", (int)GetLastError ()); 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", (int)GetLastError ()); hCom = INVALID_HANDLE_VALUE; return; } // Configure timeouts to effectively use polling COMMTIMEOUTS ct; ct.ReadIntervalTimeout = MAXDWORD; ct.ReadTotalTimeoutConstant = 0; ct.ReadTotalTimeoutMultiplier = 0; ct.WriteTotalTimeoutConstant = 0; ct.WriteTotalTimeoutMultiplier = 0; SetCommTimeouts (hCom, &ct); CSerial::Init_Registers(); InstallationSuccessful = true; receiveblock=false; ClearCommBreak (hCom); setEvent(SERIAL_POLLING_EVENT, 1); // millisecond tick }
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 = 20; rx_state=N_RX_DISC; 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 receive data when DTR is on. if (getBituSubstring("usedtr:", &bool_temp, cmd)) { if (bool_temp==1) { dtrrespect=true; transparent=true; DTR_delta=false; // connect immediately when DTR is already 1 } } // 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 (client-alike) if (getBituSubstring("inhsocket:", &bool_temp, cmd)) { #ifdef NATIVESOCKETS if (Netwrapper_GetCapabilities()&NETWRAPPER_TCP_NATIVESOCKET) { if (bool_temp==1) { int sock; if (control->cmdline->FindInt("-socket",sock,true)) { dtrrespect=false; transparent=true; LOG_MSG("Inheritance socket handle: %d",sock); if (!ClientConnect(new TCPClientSocket(sock))) return; } else { LOG_MSG("Serial%d: -socket parameter missing.",COMNUMBER); return; } } } else { LOG_MSG("Serial%d: socket inheritance not supported on this platform.", COMNUMBER); return; } #else LOG_MSG("Serial%d: socket inheritance not available.", COMNUMBER); #endif } else { // normal server/client std::string tmpstring; if (cmd->FindStringBegin("server:",tmpstring,false)) { // we are a client const char* hostnamechar=tmpstring.c_str(); size_t hostlen=strlen(hostnamechar)+1; if (hostlen>sizeof(hostnamebuffer)) { hostlen=sizeof(hostnamebuffer); hostnamebuffer[sizeof(hostnamebuffer)-1]=0; } memcpy(hostnamebuffer,hostnamechar,hostlen); clientport=(Bit16u)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 if (!ClientConnect( new TCPClientSocket((char*)hostnamebuffer,(Bit16u)clientport))) return; } else { // we are a server serverport = (Bit16u)temptcpport; if (!ServerListen()) return; } } CSerial::Init_Registers(); InstallationSuccessful = true; setCTS(dtrrespect||transparent); setDSR(dtrrespect||transparent); setRI(false); setCD(clientsocket > 0); // CD on if connection established }