Example #1
0
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;
		}
	}
}
Example #2
0
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;
	}
}
Example #3
0
PBoolean MyPCSSEndPoint::OnShowIncoming(const OpalPCSSConnection & connection) {
	return AcceptIncomingCall(connection.GetToken());
}