void CSerialModem::DoCommand() { cmdbuf[cmdpos] = 0; cmdpos = 0; //Reset for next command upcase(cmdbuf); LOG_MSG("Command sent to modem: ->%s<-\n", cmdbuf); /* Check for empty line, stops dialing and autoanswer */ if (!cmdbuf[0]) { reg[0]=0; // autoanswer off return; } //else { //MIXER_Enable(mhd.chan,false); // dialing = false; // SendRes(ResNOCARRIER); // goto ret_none; //} /* AT command set interpretation */ if ((cmdbuf[0] != 'A') || (cmdbuf[1] != 'T')) { SendRes(ResERROR); return; } if (strstr(cmdbuf,"NET0")) { telnetmode = false; SendRes(ResOK); return; } else if (strstr(cmdbuf,"NET1")) { telnetmode = true; SendRes(ResOK); return; } char * scanbuf = &cmdbuf[2]; while (1) { // LOG_MSG("loopstart ->%s<-",scanbuf); char chr = GetChar(scanbuf); switch (chr) { case 'D': { // Dial char * foundstr=&scanbuf[0]; if (*foundstr=='T' || *foundstr=='P') foundstr++; // Small protection against empty line and long string if ((!foundstr[0]) || (strlen(foundstr)>100)) { SendRes(ResERROR); return; } char* helper; // scan for and remove spaces; weird bug: with leading spaces in the string, // SDLNet_ResolveHost will return no error but not work anyway (win) while(foundstr[0]==' ') foundstr++; helper=foundstr; helper+=strlen(foundstr); while(helper[0]==' ') { helper[0]=0; helper--; } if (strlen(foundstr) >= 12) { // Check if supplied parameter only consists of digits bool isNum = true; for (Bitu i=0; i<strlen(foundstr); i++) if (foundstr[i] < '0' || foundstr[i] > '9') isNum = false; if (isNum) { // Parameter is a number with at least 12 digits => this cannot // be a valid IP/name // Transform by adding dots char buffer[128]; Bitu j = 0; for (Bitu i=0; i<strlen(foundstr); i++) { buffer[j++] = foundstr[i]; // Add a dot after the third, sixth and ninth number if (i == 2 || i == 5 || i == 8) buffer[j++] = '.'; // If the string is longer than 12 digits, // interpret the rest as port if (i == 11 && strlen(foundstr)>12) buffer[j++] = ':'; } buffer[j] = 0; foundstr = buffer; } } Dial(foundstr); return; } case 'I': // Some strings about firmware switch (ScanNumber(scanbuf)) { case 3: SendLine("DosBox Emulated Modem Firmware V1.00"); break; case 4: SendLine("Modem compiled for DosBox version " VERSION); break; } break; case 'E': // Echo on/off switch (ScanNumber(scanbuf)) { case 0: echo = false; break; case 1: echo = true; break; } break; case 'V': switch (ScanNumber(scanbuf)) { case 0: numericresponse = true; break; case 1: numericresponse = false; break; } break; case 'H': // Hang up switch (ScanNumber(scanbuf)) { case 0: if (connected) { SendRes(ResNOCARRIER); EnterIdleState(); return; } // else return ok } break; case 'O': // Return to data mode switch (ScanNumber(scanbuf)) { case 0: if (clientsocket) { commandmode = false; return; } else { SendRes(ResERROR); return; } } break; case 'T': // Tone Dial case 'P': // Pulse Dial break; case 'M': // Monitor case 'L': // Volume ScanNumber(scanbuf); break; case 'A': // Answer call if (waitingclientsocket) { AcceptIncomingCall(); } else { SendRes(ResERROR); return; } return; case 'Z': { // Reset and load profiles // scan the number away, if any ScanNumber(scanbuf); if (clientsocket) SendRes(ResNOCARRIER); Reset(); break; } case ' ': // skip space break; case 'Q': { // Response options // 0 = all on, 1 = all off, // 2 = no ring and no connect/carrier in answermode Bitu val = ScanNumber(scanbuf); if(!(val>2)) { doresponse=val; break; } else { SendRes(ResERROR); return; } } case 'S': { // Registers Bitu index=ScanNumber(scanbuf); if(index>=SREGS) { SendRes(ResERROR); return; //goto ret_none; } while(scanbuf[0]==' ') scanbuf++; // skip spaces if(scanbuf[0]=='=') { // set register scanbuf++; while(scanbuf[0]==' ') scanbuf++; // skip spaces Bitu val = ScanNumber(scanbuf); reg[index]=val; break; } else if(scanbuf[0]=='?') { // get register SendNumber(reg[index]); scanbuf++; break; } //else LOG_MSG("print reg %d with %d",index,reg[index]); } break; case '&': { // & escaped commands char cmdchar = GetChar(scanbuf); switch(cmdchar) { case 'K': { Bitu val = ScanNumber(scanbuf); if(val<5) flowcontrol=val; else { SendRes(ResERROR); return; } break; } case '\0': // end of string SendRes(ResERROR); return; default: LOG_MSG("Modem: Unhandled command: &%c%d",cmdchar,ScanNumber(scanbuf)); break; } break; } case '\\': { // \ escaped commands char cmdchar = GetChar(scanbuf); switch(cmdchar) { case 'N': // error correction stuff - not emulated if (ScanNumber(scanbuf) > 5) { SendRes(ResERROR); return; } break; case '\0': // end of string SendRes(ResERROR); return; default: LOG_MSG("Modem: Unhandled command: \\%c%d",cmdchar, ScanNumber(scanbuf)); break; } break; } case '\0': SendRes(ResOK); return; default: LOG_MSG("Modem: Unhandled command: %c%d",chr,ScanNumber(scanbuf)); break; } } }
void CSerialModem::Timer2(void) { unsigned long args = 1; bool sendbyte = true; Bitu usesize; Bit8u txval; Bitu txbuffersize =0; // Check for eventual break command if (!commandmode) cmdpause++; // Handle incoming data from serial port, read as much as available CSerial::setCTS(true); // buffer will get 'emptier', new data can be received while (tqueue->inuse()) { txval = tqueue->getb(); if (commandmode) { if (echo) { rqueue->addb(txval); //LOG_MSG("Echo back to queue: %x",txval); } if (txval==0xa) continue; //Real modem doesn't seem to skip this? else if (txval==0x8 && (cmdpos > 0)) --cmdpos; // backspace else if (txval==0xd) DoCommand(); // return else if (txval != '+') { if(cmdpos<99) { cmdbuf[cmdpos] = txval; cmdpos++; } } } else {// + character // 1000 ticks have passed, can check for pause command if (cmdpause > 1000) { if(txval ==reg[MREG_ESCAPE_CHAR]) // + { plusinc++; if(plusinc>=3) { LOG_MSG("Modem: Entering command mode(escape sequence)"); commandmode = true; SendRes(ResOK); plusinc = 0; } sendbyte=false; } else { plusinc=0; } // If not a special pause command, should go for bigger blocks to send } tmpbuf[txbuffersize] = txval; txbuffersize++; } } // while loop if (clientsocket && sendbyte && txbuffersize) { // down here it saves a lot of network traffic if(!clientsocket->SendArray(tmpbuf,txbuffersize)) { 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) { // Filter telnet commands if(telnetmode) TelnetEmulation(tmpbuf, usesize); else rqueue->adds(tmpbuf,usesize); cmdpause = 0; } } // 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(); } else { ringing=true; SendRes(ResRING); CSerial::setRI(!CSerial::getRI()); //MIXER_Enable(mhd.chan,true); ringtimer = 3000; reg[1] = 0; //Reset ring counter reg } } } if (ringing) { if (ringtimer <= 0) { reg[1]++; if ((reg[0]>0) && (reg[0]>=reg[1])) { AcceptIncomingCall(); return; } SendRes(ResRING); CSerial::setRI(!CSerial::getRI()); //MIXER_Enable(mhd.chan,true); ringtimer = 3000; } --ringtimer; } }
PBoolean MyPCSSEndPoint::OnShowIncoming(const OpalPCSSConnection & connection) { return AcceptIncomingCall(connection.GetToken()); }