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; }
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; }
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; } }
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; } }
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; }
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; } }