/* * Function ircomm_tty_set_termios (tty, old_termios) * * This routine allows the tty driver to be notified when device's * termios settings have changed. Note that a well-designed tty driver * should be prepared to accept the case where old == NULL, and try to * do something rational. */ void ircomm_tty_set_termios(struct tty_struct *tty, struct ktermios *old_termios) { struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) tty->driver_data; unsigned int cflag = tty->termios->c_cflag; IRDA_DEBUG(2, "%s()\n", __func__ ); if ((cflag == old_termios->c_cflag) && (RELEVANT_IFLAG(tty->termios->c_iflag) == RELEVANT_IFLAG(old_termios->c_iflag))) { return; } ircomm_tty_change_speed(self); /* Handle transition to B0 status */ if ((old_termios->c_cflag & CBAUD) && !(cflag & CBAUD)) { self->settings.dte &= ~(IRCOMM_DTR|IRCOMM_RTS); ircomm_param_request(self, IRCOMM_DTE, TRUE); } /* Handle transition away from B0 status */ if (!(old_termios->c_cflag & CBAUD) && (cflag & CBAUD)) { self->settings.dte |= IRCOMM_DTR; if (!(tty->termios->c_cflag & CRTSCTS) || !test_bit(TTY_THROTTLED, &tty->flags)) { self->settings.dte |= IRCOMM_RTS; } ircomm_param_request(self, IRCOMM_DTE, TRUE); } /* Handle turning off CRTSCTS */ if ((old_termios->c_cflag & CRTSCTS) && !(tty->termios->c_cflag & CRTSCTS)) { tty->hw_stopped = 0; ircomm_tty_start(tty); } }
static void ircomm_port_raise_dtr_rts(struct tty_port *port, int raise) { struct ircomm_tty_cb *self = container_of(port, struct ircomm_tty_cb, port); /* * Here, we use to lock those two guys, but as ircomm_param_request() * does it itself, I don't see the point (and I see the deadlock). * Jean II */ if (raise) self->settings.dte |= IRCOMM_RTS | IRCOMM_DTR; else self->settings.dte &= ~(IRCOMM_RTS | IRCOMM_DTR); ircomm_param_request(self, IRCOMM_DTE, TRUE); }
/* * Function ircomm_tty_change_speed (driver) * * Change speed of the driver. If the remote device is a DCE, then this * should make it change the speed of its serial port */ static void ircomm_tty_change_speed(struct ircomm_tty_cb *self) { unsigned cflag, cval; int baud; IRDA_DEBUG(2, "%s()\n", __func__ ); if (!self->tty || !self->tty->termios || !self->ircomm) return; cflag = self->tty->termios->c_cflag; /* byte size and parity */ switch (cflag & CSIZE) { case CS5: cval = IRCOMM_WSIZE_5; break; case CS6: cval = IRCOMM_WSIZE_6; break; case CS7: cval = IRCOMM_WSIZE_7; break; case CS8: cval = IRCOMM_WSIZE_8; break; default: cval = IRCOMM_WSIZE_5; break; } if (cflag & CSTOPB) cval |= IRCOMM_2_STOP_BIT; if (cflag & PARENB) cval |= IRCOMM_PARITY_ENABLE; if (!(cflag & PARODD)) cval |= IRCOMM_PARITY_EVEN; /* Determine divisor based on baud rate */ baud = tty_get_baud_rate(self->tty); if (!baud) baud = 9600; /* B0 transition handled in rs_set_termios */ self->settings.data_rate = baud; ircomm_param_request(self, IRCOMM_DATA_RATE, FALSE); /* CTS flow control flag and modem status interrupts */ if (cflag & CRTSCTS) { self->flags |= ASYNC_CTS_FLOW; self->settings.flow_control |= IRCOMM_RTS_CTS_IN; /* This got me. Bummer. Jean II */ if (self->service_type == IRCOMM_3_WIRE_RAW) IRDA_WARNING("%s(), enabling RTS/CTS on link that doesn't support it (3-wire-raw)\n", __func__); } else { self->flags &= ~ASYNC_CTS_FLOW; self->settings.flow_control &= ~IRCOMM_RTS_CTS_IN; } if (cflag & CLOCAL) self->flags &= ~ASYNC_CHECK_CD; else self->flags |= ASYNC_CHECK_CD; #if 0 /* * Set up parity check flag */ if (I_INPCK(self->tty)) driver->read_status_mask |= LSR_FE | LSR_PE; if (I_BRKINT(driver->tty) || I_PARMRK(driver->tty)) driver->read_status_mask |= LSR_BI; /* * Characters to ignore */ driver->ignore_status_mask = 0; if (I_IGNPAR(driver->tty)) driver->ignore_status_mask |= LSR_PE | LSR_FE; if (I_IGNBRK(self->tty)) { self->ignore_status_mask |= LSR_BI; /* * If we're ignore parity and break indicators, ignore * overruns too. (For real raw support). */ if (I_IGNPAR(self->tty)) self->ignore_status_mask |= LSR_OE; } #endif self->settings.data_format = cval; ircomm_param_request(self, IRCOMM_DATA_FORMAT, FALSE); ircomm_param_request(self, IRCOMM_FLOW_CONTROL, TRUE); }