static int dz_ioctl(struct tty_struct *tty, struct file *file, unsigned int cmd, unsigned long arg) { struct dz_serial *info = (struct dz_serial *) tty->driver_data; int retval; if ((cmd != TIOCGSERIAL) && (cmd != TIOCSSERIAL) && (cmd != TIOCSERCONFIG) && (cmd != TIOCSERGWILD) && (cmd != TIOCSERSWILD) && (cmd != TIOCSERGSTRUCT)) { if (tty->flags & (1 << TTY_IO_ERROR)) return -EIO; } switch (cmd) { case TCSBRK: /* SVID version: non-zero arg --> no break */ retval = tty_check_change(tty); if (retval) return retval; tty_wait_until_sent(tty, 0); if (!arg) send_break(info, HZ / 4); /* 1/4 second */ return 0; case TCSBRKP: /* support for POSIX tcsendbreak() */ retval = tty_check_change(tty); if (retval) return retval; tty_wait_until_sent(tty, 0); send_break(info, arg ? arg * (HZ / 10) : HZ / 4); return 0; case TIOCGSOFTCAR: return put_user(C_CLOCAL(tty) ? 1 : 0, (unsigned long *) arg); case TIOCSSOFTCAR: if (get_user(arg, (unsigned long *) arg)) return -EFAULT; tty->termios->c_cflag = ((tty->termios->c_cflag & ~CLOCAL) | (arg ? CLOCAL : 0)); return 0; case TIOCGSERIAL: return get_serial_info(info, (struct serial_struct *) arg); case TIOCSSERIAL: return set_serial_info(info, (struct serial_struct *) arg); case TIOCSERGETLSR: /* Get line status register */ return get_lsr_info(info, (unsigned int *) arg); case TIOCSERGSTRUCT: return copy_to_user((struct dz_serial *) arg, info, sizeof(struct dz_serial)) ? -EFAULT : 0; default: return -ENOIOCTLCMD; } return 0; }
static int rs_ioctl(struct tty_struct *tty, unsigned int cmd, unsigned long arg) { struct m68k_serial * info = (struct m68k_serial *)tty->driver_data; int retval; if (serial_paranoia_check(info, tty->name, "rs_ioctl")) return -ENODEV; if ((cmd != TIOCGSERIAL) && (cmd != TIOCSSERIAL) && (cmd != TIOCSERCONFIG) && (cmd != TIOCSERGWILD) && (cmd != TIOCSERSWILD) && (cmd != TIOCSERGSTRUCT)) { if (tty->flags & (1 << TTY_IO_ERROR)) return -EIO; } switch (cmd) { case TCSBRK: /* SVID version: non-zero arg --> no break */ retval = tty_check_change(tty); if (retval) return retval; tty_wait_until_sent(tty, 0); if (!arg) send_break(info, 250); /* 1/4 second */ return 0; case TCSBRKP: /* support for POSIX tcsendbreak() */ retval = tty_check_change(tty); if (retval) return retval; tty_wait_until_sent(tty, 0); send_break(info, arg ? arg*(100) : 250); return 0; case TIOCGSERIAL: return get_serial_info(info, (struct serial_struct *) arg); case TIOCSSERIAL: return set_serial_info(info, (struct serial_struct *) arg); case TIOCSERGETLSR: /* Get line status register */ return get_lsr_info(info, (unsigned int *) arg); case TIOCSERGSTRUCT: if (copy_to_user((struct m68k_serial *) arg, info, sizeof(struct m68k_serial))) return -EFAULT; return 0; default: return -ENOIOCTLCMD; } return 0; }
static int set_termios(struct tty_struct * tty, unsigned long arg, int opt) { struct termios tmp_termios; int retval = tty_check_change(tty); if (retval) return retval; if (opt & TERMIOS_TERMIO) { memcpy(&tmp_termios, tty->termios, sizeof(struct termios)); if (user_termio_to_kernel_termios(&tmp_termios, (struct termio *) arg)) return -EFAULT; } else { if (user_termios_to_kernel_termios(&tmp_termios, (struct termios *) arg)) return -EFAULT; } if ((opt & TERMIOS_FLUSH) && tty->ldisc.flush_buffer) tty->ldisc.flush_buffer(tty); if (opt & TERMIOS_WAIT) { tty_wait_until_sent(tty, 0); if (signal_pending(current)) return -EINTR; } change_termios(tty, &tmp_termios); return 0; }
static int write_chan(struct tty_struct * tty, struct file * file, const unsigned char * buf, unsigned int nr) { struct wait_queue wait = { current, NULL }; int c; const unsigned char *b = buf; int retval = 0; /* Job control check -- must be done at start (POSIX.1 7.1.1.4). */ if (L_TOSTOP(tty) && file->f_inode->i_rdev != CONSOLE_DEV) { retval = tty_check_change(tty); if (retval) return retval; } add_wait_queue(&tty->write_wait, &wait); while (1) { current->state = TASK_INTERRUPTIBLE; if (current->signal & ~current->blocked) { retval = -ERESTARTSYS; break; } if (tty_hung_up_p(file) || (tty->link && !tty->link->count)) { retval = -EIO; break; } if (O_OPOST(tty)) { while (nr > 0) { c = get_user(b); if (opost(c, tty) < 0) break; b++; nr--; } if (tty->driver.flush_chars) tty->driver.flush_chars(tty); } else { c = tty->driver.write(tty, 1, b, nr); b += c; nr -= c; } if (!nr) break; if (file->f_flags & O_NONBLOCK) { retval = -EAGAIN; break; } schedule(); } current->state = TASK_RUNNING; remove_wait_queue(&tty->write_wait, &wait); return (b - buf) ? b - buf : retval; }
static int set_sgttyb(struct tty_struct * tty, struct sgttyb * sgttyb) { int retval; struct sgttyb tmp; struct termios termios; retval = tty_check_change(tty); if (retval) return retval; termios = *tty->termios; if (copy_from_user(&tmp, sgttyb, sizeof(tmp))) return -EFAULT; termios.c_cc[VERASE] = tmp.sg_erase; termios.c_cc[VKILL] = tmp.sg_kill; set_sgflags(&termios, tmp.sg_flags); change_termios(tty, &termios); return 0; }
static int set_termios(struct tty_struct * tty, void __user *arg, int opt) { struct termios tmp_termios; struct tty_ldisc *ld; int retval = tty_check_change(tty); if (retval) return retval; if (opt & TERMIOS_TERMIO) { memcpy(&tmp_termios, tty->termios, sizeof(struct termios)); if (user_termio_to_kernel_termios(&tmp_termios, (struct termio __user *)arg)) return -EFAULT; } else { if (user_termios_to_kernel_termios(&tmp_termios, (struct termios __user *)arg)) return -EFAULT; } ld = tty_ldisc_ref(tty); if (ld != NULL) { if ((opt & TERMIOS_FLUSH) && ld->flush_buffer) ld->flush_buffer(tty); tty_ldisc_deref(ld); } if (opt & TERMIOS_WAIT) { tty_wait_until_sent(tty, 0); if (signal_pending(current)) return -EINTR; } change_termios(tty, &tmp_termios); return 0; }
static int xmbrs_ioctl(struct tty_struct *tty, struct file * file, unsigned int cmd, unsigned long arg) { struct xmb_serial * info = (struct xmb_serial *)tty->driver_data; unsigned int val; int retval, error; int dtr, rts; if (serial_paranoia_check(info, tty->device, "xmbrs_ioctl")) return -ENODEV; if ((cmd != TIOCGSERIAL) && (cmd != TIOCSSERIAL) && (cmd != TIOCSERCONFIG) && (cmd != TIOCSERGWILD) && (cmd != TIOCSERSWILD) && (cmd != TIOCSERGSTRUCT)) { if (tty->flags & (1 << TTY_IO_ERROR)) return -EIO; } switch (cmd) { case TCSBRK: /* SVID version: non-zero arg --> no break */ retval = tty_check_change(tty); if (retval) return retval; tty_wait_until_sent(tty, 0); if (!arg) send_break(info, HZ/4); /* 1/4 second */ return 0; case TCSBRKP: /* support for POSIX tcsendbreak() */ retval = tty_check_change(tty); if (retval) return retval; tty_wait_until_sent(tty, 0); send_break(info, arg ? arg*(HZ/10) : HZ/4); return 0; case TIOCGSOFTCAR: error = verify_area(VERIFY_WRITE, (void *) arg,sizeof(long)); if (error) return error; put_user(C_CLOCAL(tty) ? 1 : 0, (unsigned long *) arg); return 0; case TIOCSSOFTCAR: get_user(arg, (unsigned long *) arg); tty->termios->c_cflag = ((tty->termios->c_cflag & ~CLOCAL) | (arg ? CLOCAL : 0)); return 0; case TIOCGSERIAL: error = verify_area(VERIFY_WRITE, (void *) arg, sizeof(struct serial_struct)); if (error) return error; return get_serial_info(info, (struct serial_struct *) arg); case TIOCSSERIAL: return set_serial_info(info, (struct serial_struct *) arg); case TIOCSERGETLSR: /* Get line status register */ error = verify_area(VERIFY_WRITE, (void *) arg, sizeof(unsigned int)); if (error) return error; else return get_lsr_info(info, (unsigned int *) arg); case TIOCSERGSTRUCT: error = verify_area(VERIFY_WRITE, (void *) arg, sizeof(struct xmb_serial)); if (error) return error; copy_to_user((struct xmb_serial *) arg, info, sizeof(struct xmb_serial)); return 0; case TIOCMGET: if ((error = verify_area(VERIFY_WRITE, (void *) arg, sizeof(unsigned int)))) return(error); val = 0; put_user(val, (unsigned int *) arg); break; case TIOCMBIS: if ((error = verify_area(VERIFY_WRITE, (void *) arg, sizeof(unsigned int)))) return(error); get_user(val, (unsigned int *) arg); rts = (val & TIOCM_RTS) ? 1 : -1; dtr = (val & TIOCM_DTR) ? 1 : -1; break; case TIOCMBIC: if ((error = verify_area(VERIFY_WRITE, (void *) arg, sizeof(unsigned int)))) return(error); get_user(val, (unsigned int *) arg); rts = (val & TIOCM_RTS) ? 0 : -1; dtr = (val & TIOCM_DTR) ? 0 : -1; break; case TIOCMSET: if ((error = verify_area(VERIFY_WRITE, (void *) arg, sizeof(unsigned int)))) return(error); get_user(val, (unsigned int *) arg); rts = (val & TIOCM_RTS) ? 1 : 0; dtr = (val & TIOCM_DTR) ? 1 : 0; break; #ifdef TIOCSET422 case TIOCSET422: get_user(val, (unsigned int *) arg); xmb_setpa(XMBPP_PA11, (val ? 0 : XMBPP_PA11)); break; case TIOCGET422: val = (xmb_getpa() & XMBPP_PA11) ? 0 : 1; put_user(val, (unsigned int *) arg); break; #endif default: return -ENOIOCTLCMD; } return 0; }
static ssize_t write_chan(struct tty_struct * tty, struct file * file, const unsigned char * buf, size_t nr) { const unsigned char *b = buf; struct wait_queue wait = { current, NULL }; int c; ssize_t retval = 0; /* Job control check -- must be done at start (POSIX.1 7.1.1.4). */ if (L_TOSTOP(tty) && file->f_dentry->d_inode->i_rdev != CONSOLE_DEV && file->f_dentry->d_inode->i_rdev != SYSCONS_DEV) { retval = tty_check_change(tty); if (retval) return retval; } add_wait_queue(&tty->write_wait, &wait); while (1) { current->state = TASK_INTERRUPTIBLE; if (signal_pending(current)) { retval = -ERESTARTSYS; break; } if (tty_hung_up_p(file) || (tty->link && !tty->link->count)) { retval = -EIO; break; } if (O_OPOST(tty) && !(test_bit(TTY_HW_COOK_OUT, &tty->flags))) { while (nr > 0) { ssize_t num = opost_block(tty, b, nr); if (num < 0) { retval = num; goto break_out; } b += num; nr -= num; if (nr == 0) break; current->state = TASK_RUNNING; get_user(c, b); current->state = TASK_INTERRUPTIBLE; if (opost(c, tty) < 0) break; b++; nr--; } if (tty->driver.flush_chars) tty->driver.flush_chars(tty); } else { current->state = TASK_RUNNING; c = tty->driver.write(tty, 1, b, nr); current->state = TASK_INTERRUPTIBLE; if (c < 0) { retval = c; goto break_out; } b += c; nr -= c; } if (!nr) break; if (file->f_flags & O_NONBLOCK) { retval = -EAGAIN; break; } schedule(); } break_out: current->state = TASK_RUNNING; remove_wait_queue(&tty->write_wait, &wait); return (b - buf) ? b - buf : retval; }
static int rs_ioctl(struct tty_struct *tty, struct file * file, unsigned int cmd, unsigned long arg) { int error; struct NIOS_serial * info = (struct NIOS_serial *)tty->driver_data; int retval; if (serial_paranoia_check(info, tty->device, "rs_ioctl")) return -ENODEV; if ((cmd != TIOCGSERIAL) && (cmd != TIOCSSERIAL) && (cmd != TIOCSERCONFIG) && (cmd != TIOCSERGWILD) && (cmd != TIOCSERSWILD) && (cmd != TIOCSERGSTRUCT)) { if (tty->flags & (1 << TTY_IO_ERROR)) return -EIO; } switch (cmd) { case TCSBRK: /* SVID version: non-zero arg --> no break */ retval = tty_check_change(tty); if (retval) return retval; tty_wait_until_sent(tty, 0); if (!arg) send_break(info, HZ/4); /* 1/4 second */ return 0; case TCSBRKP: /* support for POSIX tcsendbreak() */ retval = tty_check_change(tty); if (retval) return retval; tty_wait_until_sent(tty, 0); send_break(info, arg ? arg*(HZ/10) : HZ/4); return 0; case TIOCGSOFTCAR: error = verify_area(VERIFY_WRITE, (void *) arg,sizeof(long)); if (error) return error; put_user(C_CLOCAL(tty) ? 1 : 0, (unsigned long *) arg); return 0; case TIOCSSOFTCAR: get_user(arg, (unsigned long *) arg); tty->termios->c_cflag = ((tty->termios->c_cflag & ~CLOCAL) | (arg ? CLOCAL : 0)); return 0; case TIOCGSERIAL: error = verify_area(VERIFY_WRITE, (void *) arg, sizeof(struct serial_struct)); if (error) return error; return get_serial_info(info, (struct serial_struct *) arg); case TIOCSSERIAL: return set_serial_info(info, (struct serial_struct *) arg); case TIOCSERGETLSR: /* Get line status register */ error = verify_area(VERIFY_WRITE, (void *) arg, sizeof(unsigned int)); if (error) return error; else return get_lsr_info(info, (unsigned int *) arg); case TIOCSERGSTRUCT: error = verify_area(VERIFY_WRITE, (void *) arg, sizeof(struct NIOS_serial)); if (error) return error; copy_to_user((struct NIOS_serial *) arg, info, sizeof(struct NIOS_serial)); return 0; default: return -ENOIOCTLCMD; } return 0; }
static int rs_360_ioctl(struct tty_struct *tty, struct file * file, unsigned int cmd, unsigned long arg) { int error; ser_info_t *info = (ser_info_t *)tty->driver_data; int retval; struct async_icount cnow; /* struct async_icount_24 cnow;*/ /* kernel counter temps */ struct serial_icounter_struct *p_cuser; /* user space */ if (serial_paranoia_check(info, tty->name, "rs_ioctl")) return -ENODEV; if ((cmd != TIOCMIWAIT) && (cmd != TIOCGICOUNT)) { if (tty->flags & (1 << TTY_IO_ERROR)) return -EIO; } switch (cmd) { case TCSBRK: /* SVID version: non-zero arg --> no break */ retval = tty_check_change(tty); if (retval) return retval; tty_wait_until_sent(tty, 0); if (signal_pending(current)) return -EINTR; if (!arg) { send_break(info, 250); /* 1/4 second */ if (signal_pending(current)) return -EINTR; } return 0; case TCSBRKP: /* support for POSIX tcsendbreak() */ retval = tty_check_change(tty); if (retval) return retval; tty_wait_until_sent(tty, 0); if (signal_pending(current)) return -EINTR; send_break(info, arg ? arg*100 : 250); if (signal_pending(current)) return -EINTR; return 0; case TIOCSBRK: retval = tty_check_change(tty); if (retval) return retval; tty_wait_until_sent(tty, 0); begin_break(info); return 0; case TIOCCBRK: retval = tty_check_change(tty); if (retval) return retval; end_break(info); return 0; #ifdef maybe case TIOCSERGETLSR: /* Get line status register */ return get_lsr_info(info, (unsigned int *) arg); #endif /* * Wait for any of the 4 modem inputs (DCD,RI,DSR,CTS) to change * - mask passed in arg for lines of interest * (use |'ed TIOCM_RNG/DSR/CD/CTS for masking) * Caller should use TIOCGICOUNT to see which one it was */ case TIOCMIWAIT: #ifdef modem_control local_irq_disable(); /* note the counters on entry */ cprev = info->state->icount; local_irq_enable(); while (1) { interruptible_sleep_on(&info->delta_msr_wait); /* see if a signal did it */ if (signal_pending(current)) return -ERESTARTSYS; local_irq_disable(); cnow = info->state->icount; /* atomic copy */ local_irq_enable(); if (cnow.rng == cprev.rng && cnow.dsr == cprev.dsr && cnow.dcd == cprev.dcd && cnow.cts == cprev.cts) return -EIO; /* no change => error */ if ( ((arg & TIOCM_RNG) && (cnow.rng != cprev.rng)) || ((arg & TIOCM_DSR) && (cnow.dsr != cprev.dsr)) || ((arg & TIOCM_CD) && (cnow.dcd != cprev.dcd)) || ((arg & TIOCM_CTS) && (cnow.cts != cprev.cts)) ) { return 0; } cprev = cnow; } /* NOTREACHED */ #else return 0; #endif /* * Get counter of input serial line interrupts (DCD,RI,DSR,CTS) * Return: write counters to the user passed counter struct * NB: both 1->0 and 0->1 transitions are counted except for * RI where only 0->1 is counted. */ case TIOCGICOUNT: local_irq_disable(); cnow = info->state->icount; local_irq_enable(); p_cuser = (struct serial_icounter_struct *) arg; /* error = put_user(cnow.cts, &p_cuser->cts); */ /* if (error) return error; */ /* error = put_user(cnow.dsr, &p_cuser->dsr); */ /* if (error) return error; */ /* error = put_user(cnow.rng, &p_cuser->rng); */ /* if (error) return error; */ /* error = put_user(cnow.dcd, &p_cuser->dcd); */ /* if (error) return error; */ put_user(cnow.cts, &p_cuser->cts); put_user(cnow.dsr, &p_cuser->dsr); put_user(cnow.rng, &p_cuser->rng); put_user(cnow.dcd, &p_cuser->dcd); return 0; default: return -ENOIOCTLCMD; } return 0; }
int n_tty_ioctl(struct tty_struct * tty, struct file * file, unsigned int cmd, unsigned long arg) { struct tty_struct * real_tty; int retval; if (tty->driver->type == TTY_DRIVER_TYPE_PTY && tty->driver->subtype == PTY_TYPE_MASTER) real_tty = tty->link; else real_tty = tty; switch (cmd) { #ifdef TIOCGETP case TIOCGETP: return get_sgttyb(real_tty, (struct sgttyb *) arg); case TIOCSETP: case TIOCSETN: return set_sgttyb(real_tty, (struct sgttyb *) arg); #endif #ifdef TIOCGETC case TIOCGETC: return get_tchars(real_tty, (struct tchars *) arg); case TIOCSETC: return set_tchars(real_tty, (struct tchars *) arg); #endif #ifdef TIOCGLTC case TIOCGLTC: return get_ltchars(real_tty, (struct ltchars *) arg); case TIOCSLTC: return set_ltchars(real_tty, (struct ltchars *) arg); #endif case TCGETS: if (kernel_termios_to_user_termios((struct termios *)arg, real_tty->termios)) return -EFAULT; return 0; case TCSETSF: return set_termios(real_tty, arg, TERMIOS_FLUSH | TERMIOS_WAIT); case TCSETSW: return set_termios(real_tty, arg, TERMIOS_WAIT); case TCSETS: return set_termios(real_tty, arg, 0); case TCGETA: return get_termio(real_tty,(struct termio *) arg); case TCSETAF: return set_termios(real_tty, arg, TERMIOS_FLUSH | TERMIOS_WAIT | TERMIOS_TERMIO); case TCSETAW: return set_termios(real_tty, arg, TERMIOS_WAIT | TERMIOS_TERMIO); case TCSETA: return set_termios(real_tty, arg, TERMIOS_TERMIO); case TCXONC: retval = tty_check_change(tty); if (retval) return retval; switch (arg) { case TCOOFF: if (!tty->flow_stopped) { tty->flow_stopped = 1; stop_tty(tty); } break; case TCOON: if (tty->flow_stopped) { tty->flow_stopped = 0; start_tty(tty); } break; case TCIOFF: if (STOP_CHAR(tty) != __DISABLED_CHAR) send_prio_char(tty, STOP_CHAR(tty)); break; case TCION: if (START_CHAR(tty) != __DISABLED_CHAR) send_prio_char(tty, START_CHAR(tty)); break; default: return -EINVAL; } return 0; case TCFLSH: retval = tty_check_change(tty); if (retval) return retval; switch (arg) { case TCIFLUSH: if (tty->ldisc.flush_buffer) tty->ldisc.flush_buffer(tty); break; case TCIOFLUSH: if (tty->ldisc.flush_buffer) tty->ldisc.flush_buffer(tty); /* fall through */ case TCOFLUSH: if (tty->driver->flush_buffer) tty->driver->flush_buffer(tty); break; default: return -EINVAL; } return 0; case TIOCOUTQ: return put_user(tty->driver->chars_in_buffer ? tty->driver->chars_in_buffer(tty) : 0, (int *) arg); case TIOCINQ: retval = tty->read_cnt; if (L_ICANON(tty)) retval = inq_canon(tty); return put_user(retval, (unsigned int *) arg); case TIOCGLCKTRMIOS: if (kernel_termios_to_user_termios((struct termios *)arg, real_tty->termios_locked)) return -EFAULT; return 0; case TIOCSLCKTRMIOS: if (!capable(CAP_SYS_ADMIN)) return -EPERM; if (user_termios_to_kernel_termios(real_tty->termios_locked, (struct termios *) arg)) return -EFAULT; return 0; case TIOCPKT: { int pktmode; if (tty->driver->type != TTY_DRIVER_TYPE_PTY || tty->driver->subtype != PTY_TYPE_MASTER) return -ENOTTY; if (get_user(pktmode, (int *) arg)) return -EFAULT; if (pktmode) { if (!tty->packet) { tty->packet = 1; tty->link->ctrl_status = 0; } } else tty->packet = 0; return 0; } case TIOCGSOFTCAR: return put_user(C_CLOCAL(tty) ? 1 : 0, (int *) arg); case TIOCSSOFTCAR: if (get_user(arg, (unsigned int *) arg)) return -EFAULT; tty->termios->c_cflag = ((tty->termios->c_cflag & ~CLOCAL) | (arg ? CLOCAL : 0)); return 0; default: return -ENOIOCTLCMD; } }
static int mcfrs_ioctl(struct tty_struct *tty, struct file * file, unsigned int cmd, unsigned long arg) { struct mcf_serial * info = (struct mcf_serial *)tty->driver_data; int retval, error; if (serial_paranoia_check(info, tty->name, "mcfrs_ioctl")) return -ENODEV; if ((cmd != TIOCGSERIAL) && (cmd != TIOCSSERIAL) && (cmd != TIOCSERCONFIG) && (cmd != TIOCSERGWILD) && (cmd != TIOCSERSWILD) && (cmd != TIOCSERGSTRUCT)) { if (tty->flags & (1 << TTY_IO_ERROR)) return -EIO; } switch (cmd) { case TCSBRK: /* SVID version: non-zero arg --> no break */ retval = tty_check_change(tty); if (retval) return retval; tty_wait_until_sent(tty, 0); if (!arg) send_break(info, HZ/4); /* 1/4 second */ return 0; case TCSBRKP: /* support for POSIX tcsendbreak() */ retval = tty_check_change(tty); if (retval) return retval; tty_wait_until_sent(tty, 0); send_break(info, arg ? arg*(HZ/10) : HZ/4); return 0; case TIOCGSERIAL: if (access_ok(VERIFY_WRITE, (void *) arg, sizeof(struct serial_struct))) return get_serial_info(info, (struct serial_struct *) arg); return -EFAULT; case TIOCSSERIAL: return set_serial_info(info, (struct serial_struct *) arg); case TIOCSERGETLSR: /* Get line status register */ if (access_ok(VERIFY_WRITE, (void *) arg, sizeof(unsigned int))) return get_lsr_info(info, (unsigned int *) arg); return -EFAULT; case TIOCSERGSTRUCT: error = copy_to_user((struct mcf_serial *) arg, info, sizeof(struct mcf_serial)); if (error) return -EFAULT; return 0; #ifdef TIOCSET422 case TIOCSET422: { unsigned int val; get_user(val, (unsigned int *) arg); mcf_setpa(MCFPP_PA11, (val ? 0 : MCFPP_PA11)); break; } case TIOCGET422: { unsigned int val; val = (mcf_getpa() & MCFPP_PA11) ? 0 : 1; put_user(val, (unsigned int *) arg); break; } #endif default: return -ENOIOCTLCMD; } return 0; }
static int send_prio_char(struct tty_struct *tty, char ch) { int was_stopped = tty->stopped; #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,26)) if (tty->ops->send_xchar) { tty->ops->send_xchar(tty, ch); #else if (tty->driver->send_xchar) { tty->driver->send_xchar(tty, ch); #endif return 0; } if (tty_write_lock(tty, 0) < 0) return -ERESTARTSYS; if (was_stopped) start_tty(tty); #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,26)) tty->ops->write(tty, &ch, 1); #else tty->driver->write(tty, &ch, 1); #endif if (was_stopped) stop_tty(tty); tty_write_unlock(tty); return 0; } int n_tty_ioctl_helper(struct tty_struct *tty, struct file *file, unsigned int cmd, unsigned long arg) { #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,26)) unsigned long flags; #endif int retval; switch (cmd) { case TCXONC: retval = tty_check_change(tty); if (retval) return retval; switch (arg) { case TCOOFF: if (!tty->flow_stopped) { tty->flow_stopped = 1; stop_tty(tty); } break; case TCOON: if (tty->flow_stopped) { tty->flow_stopped = 0; start_tty(tty); } break; case TCIOFF: if (STOP_CHAR(tty) != __DISABLED_CHAR) return send_prio_char(tty, STOP_CHAR(tty)); break; case TCION: if (START_CHAR(tty) != __DISABLED_CHAR) return send_prio_char(tty, START_CHAR(tty)); break; default: return -EINVAL; } return 0; case TCFLSH: return tty_perform_flush(tty, arg); case TIOCPKT: { int pktmode; if (tty->driver->type != TTY_DRIVER_TYPE_PTY || tty->driver->subtype != PTY_TYPE_MASTER) return -ENOTTY; if (get_user(pktmode, (int __user *) arg)) return -EFAULT; #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,26)) spin_lock_irqsave(&tty->ctrl_lock, flags); #endif if (pktmode) { if (!tty->packet) { tty->packet = 1; tty->link->ctrl_status = 0; } } else tty->packet = 0; #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,26)) spin_unlock_irqrestore(&tty->ctrl_lock, flags); #endif return 0; } default: /* Try the mode commands */ return tty_mode_ioctl(tty, file, cmd, arg); } }
static ssize_t n_tty_write(struct tty_struct *tty, struct file *file, const unsigned char *buf, size_t nr) { const unsigned char *b = buf; DECLARE_WAITQUEUE(wait, current); int c; ssize_t retval = 0; if (L_TOSTOP(tty) && file->f_op->write != redirected_tty_write) { retval = tty_check_change(tty); if (retval) return retval; } process_echoes(tty); add_wait_queue(&tty->write_wait, &wait); while (1) { set_current_state(TASK_INTERRUPTIBLE); if (signal_pending(current)) { retval = -ERESTARTSYS; break; } if (tty_hung_up_p(file) || (tty->link && !tty->link->count)) { retval = -EIO; break; } if (O_OPOST(tty) && !(test_bit(TTY_HW_COOK_OUT, &tty->flags))) { while (nr > 0) { ssize_t num = process_output_block(tty, b, nr); if (num < 0) { if (num == -EAGAIN) break; retval = num; goto break_out; } b += num; nr -= num; if (nr == 0) break; c = *b; if (process_output(c, tty) < 0) break; b++; nr--; } if (tty->ops->flush_chars) tty->ops->flush_chars(tty); } else { while (nr > 0) { c = tty->ops->write(tty, b, nr); if (c < 0) { retval = c; goto break_out; } if (!c) break; b += c; nr -= c; } } if (!nr) break; if (file->f_flags & O_NONBLOCK) { retval = -EAGAIN; break; } schedule(); } break_out: __set_current_state(TASK_RUNNING); remove_wait_queue(&tty->write_wait, &wait); if (b - buf != nr && tty->fasync) set_bit(TTY_DO_WRITE_WAKEUP, &tty->flags); return (b - buf) ? b - buf : retval; }
static ssize_t write_chan(struct tty_struct * tty, struct file * file, const unsigned char * buf, size_t nr) { const unsigned char *b = buf; DECLARE_WAITQUEUE(wait, current); int c; ssize_t retval = 0; int transaction_commit = committing_transaction(); /* Job control check -- must be done at start (POSIX.1 7.1.1.4). */ if ((!transaction_commit) && L_TOSTOP(tty) && file->f_op->write != redirected_tty_write) { retval = tty_check_change(tty); if (retval) return retval; } add_wait_queue(&tty->write_wait, &wait); while (1) { set_current_state(TASK_INTERRUPTIBLE); if (signal_pending(current)) { retval = -ERESTARTSYS; break; } if ((!transaction_commit) && (tty_hung_up_p(file) || (tty->link && !tty->link->count))) { retval = -EIO; break; } if (O_OPOST(tty) && !(test_bit(TTY_HW_COOK_OUT, &tty->flags))) { while (nr > 0) { ssize_t num = opost_block(tty, b, nr); if (num < 0) { if (num == -EAGAIN) break; retval = num; goto break_out; } b += num; nr -= num; if (nr == 0) break; c = *b; if (opost(c, tty) < 0) break; b++; nr--; } if (tty->driver->flush_chars) tty->driver->flush_chars(tty); } else { while (nr > 0) { c = tty->driver->write(tty, b, nr); if (c < 0) { retval = c; goto break_out; } if (!c) break; b += c; nr -= c; } } if (!nr) break; if ((!transaction_commit) && (tx_cache_get_file_ro(file)->f_flags & O_NONBLOCK)) { retval = -EAGAIN; break; } schedule(); } break_out: __set_current_state(TASK_RUNNING); remove_wait_queue(&tty->write_wait, &wait); return (b - buf) ? b - buf : retval; }
static int ctc_tty_ioctl(struct tty_struct *tty, struct file *file, uint cmd, ulong arg) { ctc_tty_info *info = (ctc_tty_info *) tty->driver_data; int error; int retval; if (ctc_tty_paranoia_check(info, tty->device, "ctc_tty_ioctl")) return -ENODEV; if (tty->flags & (1 << TTY_IO_ERROR)) return -EIO; switch (cmd) { case TCSBRK: /* SVID version: non-zero arg --> no break */ #ifdef CTC_DEBUG_MODEM_IOCTL printk(KERN_DEBUG "%s%d ioctl TCSBRK\n", CTC_TTY_NAME, info->line); #endif retval = tty_check_change(tty); if (retval) return retval; tty_wait_until_sent(tty, 0); return 0; case TCSBRKP: /* support for POSIX tcsendbreak() */ #ifdef CTC_DEBUG_MODEM_IOCTL printk(KERN_DEBUG "%s%d ioctl TCSBRKP\n", CTC_TTY_NAME, info->line); #endif retval = tty_check_change(tty); if (retval) return retval; tty_wait_until_sent(tty, 0); return 0; case TIOCGSOFTCAR: #ifdef CTC_DEBUG_MODEM_IOCTL printk(KERN_DEBUG "%s%d ioctl TIOCGSOFTCAR\n", CTC_TTY_NAME, info->line); #endif error = verify_area(VERIFY_WRITE, (void *) arg, sizeof(long)); if (error) return error; put_user(C_CLOCAL(tty) ? 1 : 0, (ulong *) arg); return 0; case TIOCSSOFTCAR: #ifdef CTC_DEBUG_MODEM_IOCTL printk(KERN_DEBUG "%s%d ioctl TIOCSSOFTCAR\n", CTC_TTY_NAME, info->line); #endif error = verify_area(VERIFY_READ, (void *) arg, sizeof(long)); if (error) return error; get_user(arg, (ulong *) arg); tty->termios->c_cflag = ((tty->termios->c_cflag & ~CLOCAL) | (arg ? CLOCAL : 0)); return 0; case TIOCMGET: #ifdef CTC_DEBUG_MODEM_IOCTL printk(KERN_DEBUG "%s%d ioctl TIOCMGET\n", CTC_TTY_NAME, info->line); #endif error = verify_area(VERIFY_WRITE, (void *) arg, sizeof(uint)); if (error) return error; return ctc_tty_get_ctc_tty_info(info, (uint *) arg); case TIOCMBIS: case TIOCMBIC: case TIOCMSET: error = verify_area(VERIFY_READ, (void *) arg, sizeof(uint)); if (error) return error; return ctc_tty_set_ctc_tty_info(info, cmd, (uint *) arg); case TIOCSERGETLSR: /* Get line status register */ #ifdef CTC_DEBUG_MODEM_IOCTL printk(KERN_DEBUG "%s%d ioctl TIOCSERGETLSR\n", CTC_TTY_NAME, info->line); #endif error = verify_area(VERIFY_WRITE, (void *) arg, sizeof(uint)); if (error) return error; else return ctc_tty_get_lsr_info(info, (uint *) arg); default: #ifdef CTC_DEBUG_MODEM_IOCTL printk(KERN_DEBUG "UNKNOWN ioctl 0x%08x on %s%d\n", cmd, CTC_TTY_NAME, info->line); #endif return -ENOIOCTLCMD; } return 0; }
static int rs_ioctl(struct tty_struct *tty, struct file * file, unsigned int cmd, unsigned long arg) { int error; struct async_struct * info = (struct async_struct *)tty->driver_data; int retval; if (serial_paranoia_check(info, tty->device, "rs_ioctl")) return -ENODEV; if ((cmd != TIOCGSERIAL) && (cmd != TIOCSSERIAL) && (cmd != TIOCSERCONFIG) && (cmd != TIOCSERGWILD) && (cmd != TIOCSERSWILD) && (cmd != TIOCSERGSTRUCT) && (cmd != TIOCMIWAIT) && (cmd != TIOCGICOUNT)) { if (tty->flags & (1 << TTY_IO_ERROR)) return -EIO; } switch (cmd) { case TCSBRK: /* SVID version: non-zero arg --> no break */ retval = tty_check_change(tty); if (retval) return retval; tty_wait_until_sent(tty, 0); if (!arg) send_break(info, HZ/4); /* 1/4 second */ return 0; case TCSBRKP: /* support for POSIX tcsendbreak() */ retval = tty_check_change(tty); if (retval) return retval; tty_wait_until_sent(tty, 0); send_break(info, arg ? arg*(HZ/10) : HZ/4); return 0; case TIOCGSOFTCAR: error = verify_area(VERIFY_WRITE, (void *) arg,sizeof(long)); if (error) return error; put_fs_long(C_CLOCAL(tty) ? 1 : 0, (unsigned long *) arg); return 0; case TIOCSSOFTCAR: error = verify_area(VERIFY_READ, (void *) arg, sizeof(long)); if (error) return error; arg = get_fs_long((unsigned long *) arg); tty->termios->c_cflag = ((tty->termios->c_cflag & ~CLOCAL) | (arg ? CLOCAL : 0)); return 0; case TIOCMGET: error = verify_area(VERIFY_WRITE, (void *) arg, sizeof(unsigned int)); if (error) return error; return get_modem_info(info, (unsigned int *) arg); case TIOCMBIS: case TIOCMBIC: case TIOCMSET: return set_modem_info(info, cmd, (unsigned int *) arg); default: return -ENOIOCTLCMD; } return 0; }