예제 #1
0
파일: spk_ttyio.c 프로젝트: mkrufky/linux
static int spk_ttyio_initialise_ldisc(struct spk_synth *synth)
{
	int ret = 0;
	struct tty_struct *tty;
	struct ktermios tmp_termios;
	dev_t dev;

	ret = get_dev_to_use(synth, &dev);
	if (ret)
		return ret;

	tty = tty_kopen(dev);
	if (IS_ERR(tty))
		return PTR_ERR(tty);

	if (tty->ops->open)
		ret = tty->ops->open(tty, NULL);
	else
		ret = -ENODEV;

	if (ret) {
		tty_unlock(tty);
		return ret;
	}

	clear_bit(TTY_HUPPED, &tty->flags);
	/* ensure hardware flow control is enabled */
	get_termios(tty, &tmp_termios);
	if (!(tmp_termios.c_cflag & CRTSCTS)) {
		tmp_termios.c_cflag |= CRTSCTS;
		tty_set_termios(tty, &tmp_termios);
		/*
		 * check c_cflag to see if it's updated as tty_set_termios may not return
		 * error even when no tty bits are changed by the request.
		 */
		get_termios(tty, &tmp_termios);
		if (!(tmp_termios.c_cflag & CRTSCTS))
			pr_warn("speakup: Failed to set hardware flow control\n");
	}

	tty_unlock(tty);

	ret = tty_set_ldisc(tty, N_SPEAKUP);
	if (ret)
		pr_err("speakup: Failed to set N_SPEAKUP on tty\n");

	return ret;
}
예제 #2
0
파일: serial_main.c 프로젝트: alama/freerdp
static uint32
serial_create(IRP * irp, const char * path)
{
	SERIAL_DEVICE_INFO *info;

	info = (SERIAL_DEVICE_INFO *) irp->dev->info;

	info->file = open(info->path, O_RDWR | O_NOCTTY | O_NONBLOCK);
	if (info->file == -1)
	{
		perror("open");
		return RD_STATUS_ACCESS_DENIED;
	}

	info->ptermios = (struct termios *) malloc(sizeof(struct termios));
	memset(info->ptermios, 0, sizeof(struct termios));
	info->pold_termios = (struct termios *) malloc(sizeof(struct termios));
	memset(info->pold_termios, 0, sizeof(struct termios));
	tcgetattr(info->file, info->pold_termios);

	if (!get_termios(info))
	{
		printf("INFO: SERIAL %s access denied\n", info->path);
		fflush(stdout);
		return RD_STATUS_ACCESS_DENIED;
	}

	info->ptermios->c_iflag &=
		~(IGNBRK | BRKINT | PARMRK | ISTRIP | INLCR | IGNCR | ICRNL | IXON);
	info->ptermios->c_oflag &= ~OPOST;
	info->ptermios->c_lflag &= ~(ECHO | ECHONL | ICANON | ISIG | IEXTEN);
	info->ptermios->c_cflag &= ~(CSIZE | PARENB);
	info->ptermios->c_cflag |= CS8;
	tcsetattr(info->file, TCSANOW, info->ptermios);

	info->event_txempty = 0;
	info->event_cts = 0;
	info->event_dsr = 0;
	info->event_rlsd = 0;
	info->event_pending = 0;

	irp->fileID = info->devman->id_sequence++;

	/* all read and writes should be non blocking */
	if (fcntl(info->file, F_SETFL, O_NONBLOCK) == -1)
		perror("fcntl");

	info->read_total_timeout_constant = 5;
	return RD_STATUS_SUCCESS;
}
예제 #3
0
int tty_ioctl(struct inode * inode, struct file * file,
	unsigned int cmd, unsigned int arg)
{
	struct tty_struct * tty;
	struct tty_struct * other_tty;
	int pgrp;
	int dev;

	if (MAJOR(file->f_rdev) != 4) {
		printk("tty_ioctl: tty pseudo-major != 4\n");
		return -EINVAL;
	}
	dev = MINOR(file->f_rdev);
	tty = TTY_TABLE(dev);
	if (!tty)
		return -EINVAL;

	if (IS_A_PTY(dev))
		other_tty = tty_table[PTY_OTHER(dev)];
	else
		other_tty = NULL;
		
	switch (cmd) {
		case TCGETS:
			return get_termios(tty,(struct termios *) arg);
		case TCSETSF:
			flush_input(tty);
		/* fallthrough */
		case TCSETSW:
			wait_until_sent(tty);
		/* fallthrough */
		case TCSETS:
			return set_termios(tty,(struct termios *) arg, dev);
		case TCGETA:
			return get_termio(tty,(struct termio *) arg);
		case TCSETAF:
			flush_input(tty);
		/* fallthrough */
		case TCSETAW:
			wait_until_sent(tty); /* fallthrough */
		case TCSETA:
			return set_termio(tty,(struct termio *) arg, dev);
		case TCXONC:
			switch (arg) {
			case TCOOFF:
				tty->stopped = 1;
				TTY_WRITE_FLUSH(tty);
				return 0;
			case TCOON:
				tty->stopped = 0;
				TTY_WRITE_FLUSH(tty);
				return 0;
			case TCIOFF:
				if (STOP_CHAR(tty))
					put_tty_queue(STOP_CHAR(tty),
						      &tty->write_q);
				return 0;
			case TCION:
				if (START_CHAR(tty))
					put_tty_queue(START_CHAR(tty),
						      &tty->write_q);
				return 0;
			}
			return -EINVAL; /* not implemented */
		case TCFLSH:
			if (arg==0)
				flush_input(tty);
			else if (arg==1)
				flush_output(tty);
			else if (arg==2) {
				flush_input(tty);
				flush_output(tty);
			} else
				return -EINVAL;
			return 0;
		case TIOCEXCL:
			return -EINVAL; /* not implemented */
		case TIOCNXCL:
			return -EINVAL; /* not implemented */
		case TIOCSCTTY:
			return -EINVAL; /* set controlling term NI */
		case TIOCGPGRP:
			verify_area((void *) arg,4);
			put_fs_long(tty->pgrp,(unsigned long *) arg);
			return 0;
		case TIOCSPGRP:
			if ((current->tty < 0) ||
			    (current->tty != dev) ||
			    (tty->session != current->session))
				return -ENOTTY;
			pgrp=get_fs_long((unsigned long *) arg);
			if (pgrp < 0)
				return -EINVAL;
			if (session_of_pgrp(pgrp) != current->session)
				return -EPERM;
			tty->pgrp = pgrp;			
			return 0;
		case TIOCOUTQ:
			verify_area((void *) arg,4);
			put_fs_long(CHARS(&tty->write_q),
				    (unsigned long *) arg);
			return 0;
		case TIOCINQ:
			verify_area((void *) arg,4);
			if (L_CANON(tty) && !tty->secondary.data)
				put_fs_long(0, (unsigned long *) arg);
			else
				put_fs_long(CHARS(&tty->secondary),
					(unsigned long *) arg);
			return 0;
		case TIOCSTI:
			return -EINVAL; /* not implemented */
		case TIOCGWINSZ:
			return get_window_size(tty,(struct winsize *) arg);
		case TIOCSWINSZ:
			if (IS_A_PTY_MASTER(dev))
				set_window_size(other_tty,(struct winsize *) arg);
			return set_window_size(tty,(struct winsize *) arg);
		case TIOCGSOFTCAR:
			return -EINVAL; /* not implemented */
		case TIOCSSOFTCAR:
			return -EINVAL; /* not implemented */
		case TIOCLINUX:
			switch (get_fs_byte((char *)arg))
			{
				case 0: 
					return do_screendump(arg);
				case 1: 
					return do_get_ps_info(arg);
				default: 
					return -EINVAL;
			}
		case TIOCCONS:
			if (!IS_A_PTY(dev))
				return -EINVAL;
			if (redirect)
				return -EBUSY;
			if (!suser())
				return -EPERM;
			if (IS_A_PTY_MASTER(dev))
				redirect = other_tty;
			else
				redirect = tty;
			return 0;
		case FIONBIO:
			if (arg)
				file->f_flags |= O_NONBLOCK;
			else
				file->f_flags &= ~O_NONBLOCK;
			return 0;
		case TIOCNOTTY:
			if (MINOR(file->f_rdev) != current->tty)
				return -EINVAL;
			current->tty = -1;
			if (current->leader) {
				if (tty->pgrp > 0)
					kill_pg(tty->pgrp, SIGHUP, 0);
				tty->pgrp = -1;
				tty->session = 0;
			}
			return 0;

	       case TIOCPKT:
			{
			   int on;
			   if (!IS_A_PTY_MASTER(dev))
			     return (-EINVAL);
			   verify_area ((unsigned long *)arg, sizeof (int));
			   on=get_fs_long ((unsigned long *)arg);
			   if (on )
			     tty->packet = 1;
			   else
			     tty->packet = 0;
			   return (0);
			}

		default:
			if (tty->ioctl)
				return (tty->ioctl)(tty, file, cmd, arg);
			else
				return -EINVAL;
	}
}
예제 #4
0
int tty_ioctl(int dev, int cmd, int arg)
{
	struct tty_struct * tty;
	if (MAJOR(dev) == 5) {
		dev=current->tty;
		if (dev<0)
			panic("tty_ioctl: dev<0");
	} else
		dev=MINOR(dev);
	tty = dev + tty_table;
	switch (cmd) {
		case TCGETS:
			return get_termios(tty,(struct termios *) arg);
		case TCSETSF:
			flush(&tty->read_q); /* fallthrough */
		case TCSETSW:
			wait_until_sent(tty); /* fallthrough */
		case TCSETS:
			return set_termios(tty,(struct termios *) arg);
		case TCGETA:
			return get_termio(tty,(struct termio *) arg);
		case TCSETAF:
			flush(&tty->read_q); /* fallthrough */
		case TCSETAW:
			wait_until_sent(tty); /* fallthrough */
		case TCSETA:
			return set_termio(tty,(struct termio *) arg);
		case TCSBRK:
			if (!arg) {
				wait_until_sent(tty);
				send_break(tty);
			}
			return 0;
		case TCXONC:
			return -EINVAL; /* not implemented */
		case TCFLSH:
			if (arg==0)
				flush(&tty->read_q);
			else if (arg==1)
				flush(&tty->write_q);
			else if (arg==2) {
				flush(&tty->read_q);
				flush(&tty->write_q);
			} else
				return -EINVAL;
			return 0;
		case TIOCEXCL:
			return -EINVAL; /* not implemented */
		case TIOCNXCL:
			return -EINVAL; /* not implemented */
		case TIOCSCTTY:
			return -EINVAL; /* set controlling term NI */
		case TIOCGPGRP:
			verify_area((void *) arg,4);
			put_fs_long(tty->pgrp,(unsigned long *) arg);
			return 0;
		case TIOCSPGRP:
			tty->pgrp=get_fs_long((unsigned long *) arg);
			return 0;
		case TIOCOUTQ:
			verify_area((void *) arg,4);
			put_fs_long(CHARS(tty->write_q),(unsigned long *) arg);
			return 0;
		case TIOCSTI:
			return -EINVAL; /* not implemented */
		case TIOCGWINSZ:
			return -EINVAL; /* not implemented */
		case TIOCSWINSZ:
			return -EINVAL; /* not implemented */
		case TIOCMGET:
			return -EINVAL; /* not implemented */
		case TIOCMBIS:
			return -EINVAL; /* not implemented */
		case TIOCMBIC:
			return -EINVAL; /* not implemented */
		case TIOCMSET:
			return -EINVAL; /* not implemented */
		case TIOCGSOFTCAR:
			return -EINVAL; /* not implemented */
		case TIOCSSOFTCAR:
			return -EINVAL; /* not implemented */
		default:
			return -EINVAL;
	}
}
예제 #5
0
파일: serial_main.c 프로젝트: alama/freerdp
static uint32
serial_control(IRP * irp)
{
	int flush_mask, purge_mask;
	uint32 result, modemstate;
	uint8 immediate;
	int size = 0, ret = RD_STATUS_SUCCESS;
	SERIAL_DEVICE_INFO *info = (SERIAL_DEVICE_INFO *) irp->dev->info;
	char *inbuf = irp->inputBuffer;
	char *outbuf = NULL;

	/* the server commands, we obbey */
	switch (irp->ioControlCode)
	{
		case IOCTL_SERIAL_SET_BAUD_RATE:
			info->baud_rate = GET_UINT32(inbuf, 0);
			set_termios(info);
			LLOGLN(10, ("serial_ioctl -> SERIAL_SET_BAUD_RATE %d", info->baud_rate));
			break;
		case IOCTL_SERIAL_GET_BAUD_RATE:
			size = 4;
			outbuf = malloc(size);
			SET_UINT32(outbuf, 0, info->baud_rate);
			LLOGLN(10, ("serial_ioctl -> SERIAL_GET_BAUD_RATE %d", info->baud_rate));
			break;
		case IOCTL_SERIAL_SET_QUEUE_SIZE:
			info->queue_in_size = GET_UINT32(inbuf, 0);
			info->queue_out_size = GET_UINT32(inbuf, 4);
			LLOGLN(10, ("serial_ioctl -> SERIAL_SET_QUEUE_SIZE in %d out %d", info->queue_in_size, info->queue_out_size));
			break;
		case IOCTL_SERIAL_SET_LINE_CONTROL:
			info->stop_bits = GET_UINT8(inbuf, 0);
			info->parity = GET_UINT8(inbuf, 1);
			info->word_length = GET_UINT8(inbuf, 2);
			set_termios(info);
			LLOGLN(10, ("serial_ioctl -> SERIAL_SET_LINE_CONTROL stop %d parity %d word %d",
					info->stop_bits, info->parity, info->word_length));
			break;
		case IOCTL_SERIAL_GET_LINE_CONTROL:
			LLOGLN(10, ("serial_ioctl -> SERIAL_GET_LINE_CONTROL"));
			size = 3;
			outbuf = malloc(size);
			SET_UINT8(outbuf, 0, info->stop_bits);
			SET_UINT8(outbuf, 1, info->parity);
			SET_UINT8(outbuf, 2, info->word_length);
			break;
		case IOCTL_SERIAL_IMMEDIATE_CHAR:
			LLOGLN(10, ("serial_ioctl -> SERIAL_IMMEDIATE_CHAR"));
			immediate = GET_UINT8(inbuf, 0);
			serial_write_data(irp, &immediate, 1);
			break;
		case IOCTL_SERIAL_CONFIG_SIZE:
			LLOGLN(10, ("serial_ioctl -> SERIAL_CONFIG_SIZE"));
			size = 4;
			outbuf = malloc(size);
			SET_UINT32(outbuf, 0, 0);
			break;
		case IOCTL_SERIAL_GET_CHARS:
			LLOGLN(10, ("serial_ioctl -> SERIAL_GET_CHARS"));
			size = 6;
			outbuf = malloc(size);
			memcpy(outbuf, info->chars, size);
			break;
		case IOCTL_SERIAL_SET_CHARS:
			LLOGLN(10, ("serial_ioctl -> SERIAL_SET_CHARS"));
			memcpy(info->chars, inbuf, 6);
			set_termios(info);
			break;
		case IOCTL_SERIAL_GET_HANDFLOW:
			LLOGLN(10, ("serial_ioctl -> IOCTL_SERIAL_GET_HANDFLOW"));
			size = 16;
			outbuf = malloc(size);
			get_termios(info);
			SET_UINT32(outbuf, 0, info->control);
			SET_UINT32(outbuf, 4, info->xonoff);
			SET_UINT32(outbuf, 8, info->onlimit);
			SET_UINT32(outbuf, 12, info->offlimit);
			break;
		case IOCTL_SERIAL_SET_HANDFLOW:
			info->control = GET_UINT32(inbuf, 0);
			info->xonoff = GET_UINT32(inbuf, 4);
			info->onlimit = GET_UINT32(inbuf, 8);
			info->offlimit = GET_UINT32(inbuf, 12);
			LLOGLN(10, ("serial_ioctl -> IOCTL_SERIAL_SET_HANDFLOW %x %x %x %x",
				      info->control, info->xonoff, info->onlimit, info->onlimit));
			set_termios(info);
			break;
		case IOCTL_SERIAL_SET_TIMEOUTS:
			info->read_interval_timeout = GET_UINT32(inbuf, 0);
			info->read_total_timeout_multiplier = GET_UINT32(inbuf, 4);
			info->read_total_timeout_constant = GET_UINT32(inbuf, 8);
			info->write_total_timeout_multiplier = GET_UINT32(inbuf, 12);
			info->write_total_timeout_constant = GET_UINT32(inbuf, 16);

			/* http://www.codeproject.com/KB/system/chaiyasit_t.aspx, see 'ReadIntervalTimeout' section
				http://msdn.microsoft.com/en-us/library/ms885171.aspx */
			if (info->read_interval_timeout == SERIAL_TIMEOUT_MAX)
			{
				info->read_interval_timeout = 0;
				info->read_total_timeout_multiplier = 0;
			}

			LLOGLN(10, ("serial_ioctl -> SERIAL_SET_TIMEOUTS read timeout %d %d %d",
				      info->read_interval_timeout,
				      info->read_total_timeout_multiplier,
				      info->read_total_timeout_constant));
			break;
		case IOCTL_SERIAL_GET_TIMEOUTS:
			LLOGLN(10, ("serial_ioctl -> SERIAL_GET_TIMEOUTS read timeout %d %d %d",
				      info->read_interval_timeout,
				      info->read_total_timeout_multiplier,
				      info->read_total_timeout_constant));
			size = 20;
			outbuf = malloc(size);
			SET_UINT32(outbuf, 0, info->read_interval_timeout);
			SET_UINT32(outbuf, 4, info->read_total_timeout_multiplier);
			SET_UINT32(outbuf, 8, info->read_total_timeout_constant);
			SET_UINT32(outbuf, 12, info->write_total_timeout_multiplier);
			SET_UINT32(outbuf, 16, info->write_total_timeout_constant);
			break;
		case IOCTL_SERIAL_GET_WAIT_MASK:
			LLOGLN(10, ("serial_ioctl -> SERIAL_GET_WAIT_MASK %X", info->wait_mask));
			size = 4;
			outbuf = malloc(size);
			SET_UINT32(outbuf, 0, info->wait_mask);
			break;
		case IOCTL_SERIAL_SET_WAIT_MASK:
			info->wait_mask = GET_UINT32(inbuf, 0);
			LLOGLN(10, ("serial_ioctl -> SERIAL_SET_WAIT_MASK %X", info->wait_mask));
			break;
		case IOCTL_SERIAL_SET_DTR:
			LLOGLN(10, ("serial_ioctl -> SERIAL_SET_DTR"));
			ioctl(info->file, TIOCMGET, &result);
			result |= TIOCM_DTR;
			ioctl(info->file, TIOCMSET, &result);
			info->dtr = 1;
			break;
		case IOCTL_SERIAL_CLR_DTR:
			LLOGLN(10, ("serial_ioctl -> SERIAL_CLR_DTR"));
			ioctl(info->file, TIOCMGET, &result);
			result &= ~TIOCM_DTR;
			ioctl(info->file, TIOCMSET, &result);
			info->dtr = 0;
			break;
		case IOCTL_SERIAL_SET_RTS:
			LLOGLN(10, ("serial_ioctl -> SERIAL_SET_RTS"));
			ioctl(info->file, TIOCMGET, &result);
			result |= TIOCM_RTS;
			ioctl(info->file, TIOCMSET, &result);
			info->rts = 1;
			break;
		case IOCTL_SERIAL_CLR_RTS:
			LLOGLN(10, ("serial_ioctl -> SERIAL_CLR_RTS"));
			ioctl(info->file, TIOCMGET, &result);
			result &= ~TIOCM_RTS;
			ioctl(info->file, TIOCMSET, &result);
			info->rts = 0;
			break;
		case IOCTL_SERIAL_GET_MODEMSTATUS:
			modemstate = 0;
#ifdef TIOCMGET
			ioctl(info->file, TIOCMGET, &result);
			if (result & TIOCM_CTS)
				modemstate |= SERIAL_MS_CTS;
			if (result & TIOCM_DSR)
				modemstate |= SERIAL_MS_DSR;
			if (result & TIOCM_RNG)
				modemstate |= SERIAL_MS_RNG;
			if (result & TIOCM_CAR)
				modemstate |= SERIAL_MS_CAR;
			if (result & TIOCM_DTR)
				modemstate |= SERIAL_MS_DTR;
			if (result & TIOCM_RTS)
				modemstate |= SERIAL_MS_RTS;
#endif
			LLOGLN(10, ("serial_ioctl -> SERIAL_GET_MODEMSTATUS %X", modemstate));
			size = 4;
			outbuf = malloc(size);
			SET_UINT32(outbuf, 0, modemstate);
			break;
		case IOCTL_SERIAL_GET_COMMSTATUS:
			size = 18;
			outbuf = malloc(size);
			SET_UINT32(outbuf, 0, 0);	/* Errors */
			SET_UINT32(outbuf, 4, 0);	/* Hold reasons */

			result = 0;
#ifdef TIOCINQ
			ioctl(info->file, TIOCINQ, &result);
#endif
			SET_UINT32(outbuf, 8, result);	/* Amount in in queue */
			if (result)
				LLOGLN(10, ("serial_ioctl -> SERIAL_GET_COMMSTATUS in queue %d", result));

			result = 0;
#ifdef TIOCOUTQ
			ioctl(info->file, TIOCOUTQ, &result);
#endif
			SET_UINT32(outbuf, 12, result);	/* Amount in out queue */
			LLOGLN(10, ("serial_ioctl -> SERIAL_GET_COMMSTATUS out queue %d", result));

			SET_UINT8(outbuf, 16, 0);	/* EofReceived */
			SET_UINT8(outbuf, 17, 0);	/* WaitForImmediate */
			break;
		case IOCTL_SERIAL_PURGE:
			purge_mask = GET_UINT32(inbuf, 0);
			LLOGLN(10, ("serial_ioctl -> SERIAL_PURGE purge_mask %X", purge_mask));
			flush_mask = 0;
			if (purge_mask & SERIAL_PURGE_TXCLEAR)
				flush_mask |= TCOFLUSH;
			if (purge_mask & SERIAL_PURGE_RXCLEAR)
				flush_mask |= TCIFLUSH;
			if (flush_mask != 0)
				tcflush(info->file, flush_mask);

			if (purge_mask & SERIAL_PURGE_TXABORT)
				irp->abortIO |= RDPDR_ABORT_IO_WRITE;
			if(purge_mask & SERIAL_PURGE_RXABORT)
				irp->abortIO |= RDPDR_ABORT_IO_READ;
			break;
		case IOCTL_SERIAL_WAIT_ON_MASK:
			LLOGLN(10, ("serial_ioctl -> SERIAL_WAIT_ON_MASK %X", info->wait_mask));
			info->event_pending = 1;
			if (serial_get_event(irp, &result))
			{
				size = 4;
				outbuf = malloc(size);
				LLOGLN(10, ("WAIT end  event = %x", result));
				SET_UINT32(outbuf, 0, result);
				break;
			}
			irp->outputBufferLength = 4;
			ret = RD_STATUS_PENDING;
			break;
		case IOCTL_SERIAL_SET_BREAK_ON:
			LLOGLN(10, ("serial_ioctl -> SERIAL_SET_BREAK_ON"));
			tcsendbreak(info->file, 0);
			break;
		case IOCTL_SERIAL_RESET_DEVICE:
			LLOGLN(10, ("serial_ioctl -> SERIAL_RESET_DEVICE"));
			break;
		case IOCTL_SERIAL_SET_BREAK_OFF:
			LLOGLN(10, ("serial_ioctl -> SERIAL_SET_BREAK_OFF"));
			break;
		case IOCTL_SERIAL_SET_XOFF:
			LLOGLN(10, ("serial_ioctl -> SERIAL_SET_XOFF"));
			break;
		case IOCTL_SERIAL_SET_XON:
			LLOGLN(10, ("serial_ioctl -> SERIAL_SET_XON"));
			tcflow(info->file, TCION);
			break;
		default:
			LLOGLN(10, ("NOT FOUND IoControlCode SERIAL IOCTL %d", irp->ioControlCode));
			return RD_STATUS_INVALID_PARAMETER;
	}

	irp->outputBuffer = outbuf;
	irp->outputBufferLength = size;

	return ret;
}
예제 #6
0
int tty_ioctl(int dev, int cmd, int arg)
{
	struct tty_struct * tty;
	struct tty_struct * other_tty;
	int pgrp;

	if (MAJOR(dev) == 5) {
		dev = current->tty;
		if (dev<0)
			return -EINVAL;
	} else
		dev=MINOR(dev);
	tty = tty_table + (dev ? ((dev < 64)? dev-1:dev) : fg_console);

	if (IS_A_PTY(dev))
		other_tty = tty_table + PTY_OTHER(dev);
	else
		other_tty = NULL;
		
	if (!(tty->write_q && tty->read_q && tty->secondary && tty->write))
		return -EINVAL;
	switch (cmd) {
		case TCGETS:
			return get_termios(tty,(struct termios *) arg);
		case TCSETSF:
			flush(tty->read_q);
			flush(tty->secondary);
			if (other_tty)
				flush(other_tty->write_q);
		/* fallthrough */
		case TCSETSW:
			wait_until_sent(tty);
		/* fallthrough */
		case TCSETS:
			return set_termios(tty,(struct termios *) arg, dev);
		case TCGETA:
			return get_termio(tty,(struct termio *) arg);
		case TCSETAF:
			flush(tty->read_q);
			flush(tty->secondary);
			if (other_tty)
				flush(other_tty->write_q);
		/* fallthrough */
		case TCSETAW:
			wait_until_sent(tty); /* fallthrough */
		case TCSETA:
			return set_termio(tty,(struct termio *) arg, dev);
		case TCSBRK:
			if (!arg) {
				wait_until_sent(tty);
				send_break(tty);
			}
			return 0;
		case TCXONC:
			switch (arg) {
			case TCOOFF:
				tty->stopped = 1;
				tty->write(tty);
				return 0;
			case TCOON:
				tty->stopped = 0;
				tty->write(tty);
				return 0;
			case TCIOFF:
				if (STOP_CHAR(tty))
					PUTCH(STOP_CHAR(tty),tty->write_q);
				return 0;
			case TCION:
				if (START_CHAR(tty))
					PUTCH(START_CHAR(tty),tty->write_q);
				return 0;
			}
			return -EINVAL; /* not implemented */
		case TCFLSH:
			if (arg==0) {
				flush(tty->read_q);
				flush(tty->secondary);
				if (other_tty)
					flush(other_tty->write_q);
			} else if (arg==1)
				flush(tty->write_q);
			else if (arg==2) {
				flush(tty->read_q);
				flush(tty->secondary);
				flush(tty->write_q);
				if (other_tty)
					flush(other_tty->write_q);
			} else
				return -EINVAL;
			return 0;
		case TIOCEXCL:
			return -EINVAL; /* not implemented */
		case TIOCNXCL:
			return -EINVAL; /* not implemented */
		case TIOCSCTTY:
			return -EINVAL; /* set controlling term NI */
		case TIOCGPGRP:
			verify_area((void *) arg,4);
			put_fs_long(tty->pgrp,(unsigned long *) arg);
			return 0;
		case TIOCSPGRP:
			if ((current->tty < 0) ||
			    (current->tty != dev) ||
			    (tty->session != current->session))
				return -ENOTTY;
			pgrp=get_fs_long((unsigned long *) arg);
			if (pgrp < 0)
				return -EINVAL;
			if (session_of_pgrp(pgrp) != current->session)
				return -EPERM;
			tty->pgrp = pgrp;			
			return 0;
		case TIOCOUTQ:
			verify_area((void *) arg,4);
			put_fs_long(CHARS(tty->write_q),(unsigned long *) arg);
			return 0;
		case TIOCINQ:
			verify_area((void *) arg,4);
			put_fs_long(CHARS(tty->secondary),
				(unsigned long *) arg);
			return 0;
		case TIOCSTI:
			return -EINVAL; /* not implemented */
		case TIOCGWINSZ:
			return get_window_size(tty,(struct winsize *) arg);
		case TIOCSWINSZ:
			if (other_tty)
				set_window_size(other_tty,(struct winsize *) arg);
			return set_window_size(tty,(struct winsize *) arg);
		case TIOCMGET:
			return -EINVAL; /* not implemented */
		case TIOCMBIS:
			return -EINVAL; /* not implemented */
		case TIOCMBIC:
			return -EINVAL; /* not implemented */
		case TIOCMSET:
			return -EINVAL; /* not implemented */
		case TIOCGSOFTCAR:
			return -EINVAL; /* not implemented */
		case TIOCSSOFTCAR:
			return -EINVAL; /* not implemented */
		case TIOCLINUX:
			switch (get_fs_byte((char *)arg))
			{
				case 0: 
					return do_screendump(arg);
				case 1: 
					return do_get_ps_info(arg);
				default: 
					return -EINVAL;
			}
		default:
			return -EINVAL;
	}
}