Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 70687
b: refs/heads/master
c: 5f519d7
h: refs/heads/master
i:
  70685: 93c2de4
  70683: 347ce01
  70679: 57d95c1
  70671: a24aad8
  70655: 8cebdcc
v: v3
  • Loading branch information
Alan Cox authored and Linus Torvalds committed Oct 17, 2007
1 parent 4cd21c0 commit 4fb2f7d
Show file tree
Hide file tree
Showing 3 changed files with 76 additions and 11 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: ca025282e9f13471cd4bf44d854bbd6dcbcb39c1
refs/heads/master: 5f519d728169fa9975bcba001de425f11e18e8e3
82 changes: 72 additions & 10 deletions trunk/drivers/char/tty_ioctl.c
Original file line number Diff line number Diff line change
Expand Up @@ -206,8 +206,6 @@ speed_t tty_termios_input_baud_rate(struct ktermios *termios)

EXPORT_SYMBOL(tty_termios_input_baud_rate);

#ifdef BOTHER

/**
* tty_termios_encode_baud_rate
* @termios: ktermios structure holding user requested state
Expand All @@ -225,6 +223,9 @@ EXPORT_SYMBOL(tty_termios_input_baud_rate);
*
* Locking: Caller should hold termios lock. This is already held
* when calling this function from the driver termios handler.
*
* The ifdefs deal with platforms whose owners have yet to update them
* and will all go away once this is done.
*/

void tty_termios_encode_baud_rate(struct ktermios *termios, speed_t ibaud, speed_t obaud)
Expand All @@ -234,9 +235,13 @@ void tty_termios_encode_baud_rate(struct ktermios *termios, speed_t ibaud, speed
int iclose = ibaud/50, oclose = obaud/50;
int ibinput = 0;

if (obaud == 0) /* CD dropped */
ibaud = 0; /* Clear ibaud to be sure */

termios->c_ispeed = ibaud;
termios->c_ospeed = obaud;

#ifdef BOTHER
/* If the user asked for a precise weird speed give a precise weird
answer. If they asked for a Bfoo speed they many have problems
digesting non-exact replies so fuzz a bit */
Expand All @@ -247,32 +252,60 @@ void tty_termios_encode_baud_rate(struct ktermios *termios, speed_t ibaud, speed
iclose = 0;
if ((termios->c_cflag >> IBSHIFT) & CBAUD)
ibinput = 1; /* An input speed was specified */

#endif
termios->c_cflag &= ~CBAUD;

/*
* Our goal is to find a close match to the standard baud rate
* returned. Walk the baud rate table and if we get a very close
* match then report back the speed as a POSIX Bxxxx value by
* preference
*/

do {
if (obaud - oclose >= baud_table[i] && obaud + oclose <= baud_table[i]) {
termios->c_cflag |= baud_bits[i];
ofound = i;
}
if (ibaud - iclose >= baud_table[i] && ibaud + iclose <= baud_table[i]) {
/* For the case input == output don't set IBAUD bits if the user didn't do so */
if (ofound != i || ibinput)
if (ofound == i && !ibinput)
ifound = i;
#ifdef IBSHIFT
else {
ifound = i;
termios->c_cflag |= (baud_bits[i] << IBSHIFT);
ifound = i;
}
#endif
}
} while (++i < n_baud_table);

/*
* If we found no match then use BOTHER if provided or warn
* the user their platform maintainer needs to wake up if not.
*/
#ifdef BOTHER
if (ofound == -1)
termios->c_cflag |= BOTHER;
/* Set exact input bits only if the input and output differ or the
user already did */
if (ifound == -1 && (ibaud != obaud || ibinput))
termios->c_cflag |= (BOTHER << IBSHIFT);
#else
if (ifound == -1 || ofound == -1) {
static int warned;
if (!warned++)
printk(KERN_WARNING "tty: Unable to return correct "
"speed data as your architecture needs updating.\n");
}
#endif
}

EXPORT_SYMBOL_GPL(tty_termios_encode_baud_rate);

#endif
void tty_encode_baud_rate(struct tty_struct *tty, speed_t ibaud, speed_t obaud)
{
tty_termios_encode_baud_rate(tty->termios, ibaud, obaud);
}
EXPORT_SYMBOL_GPL(tty_encode_baud_rate);

/**
* tty_get_baud_rate - get tty bit rates
Expand Down Expand Up @@ -303,6 +336,29 @@ speed_t tty_get_baud_rate(struct tty_struct *tty)

EXPORT_SYMBOL(tty_get_baud_rate);

/**
* tty_termios_copy_hw - copy hardware settings
* @new: New termios
* @old: Old termios
*
* Propogate the hardware specific terminal setting bits from
* the old termios structure to the new one. This is used in cases
* where the hardware does not support reconfiguration or as a helper
* in some cases where only minimal reconfiguration is supported
*/

void tty_termios_copy_hw(struct ktermios *new, struct ktermios *old)
{
/* The bits a dumb device handles in software. Smart devices need
to always provide a set_termios method */
new->c_cflag &= HUPCL | CREAD | CLOCAL;
new->c_cflag |= old->c_cflag & ~(HUPCL | CREAD | CLOCAL);
new->c_ispeed = old->c_ispeed;
new->c_ospeed = old->c_ospeed;
}

EXPORT_SYMBOL(tty_termios_copy_hw);

/**
* change_termios - update termios values
* @tty: tty to update
Expand Down Expand Up @@ -340,13 +396,12 @@ static void change_termios(struct tty_struct * tty, struct ktermios * new_termio
tty->erasing = 0;
}


/* This bit should be in the ldisc code */
if (canon_change && !L_ICANON(tty) && tty->read_cnt)
/* Get characters left over from canonical mode. */
wake_up_interruptible(&tty->read_wait);

/* See if packet mode change of state. */

if (tty->link && tty->link->packet) {
int old_flow = ((old_termios.c_iflag & IXON) &&
(old_termios.c_cc[VSTOP] == '\023') &&
Expand All @@ -366,6 +421,8 @@ static void change_termios(struct tty_struct * tty, struct ktermios * new_termio

if (tty->driver->set_termios)
(*tty->driver->set_termios)(tty, &old_termios);
else
tty_termios_copy_hw(tty->termios, &old_termios);

ld = tty_ldisc_ref(tty);
if (ld != NULL) {
Expand Down Expand Up @@ -440,6 +497,11 @@ static int set_termios(struct tty_struct * tty, void __user *arg, int opt)
}

change_termios(tty, &tmp_termios);

/* FIXME: Arguably if tmp_termios == tty->termios AND the
actual requested termios was not tmp_termios then we may
want to return an error as no user requested change has
succeeded */
return 0;
}

Expand Down
3 changes: 3 additions & 0 deletions trunk/include/linux/tty.h
Original file line number Diff line number Diff line change
Expand Up @@ -316,6 +316,9 @@ extern void tty_flip_buffer_push(struct tty_struct *tty);
extern speed_t tty_get_baud_rate(struct tty_struct *tty);
extern speed_t tty_termios_baud_rate(struct ktermios *termios);
extern speed_t tty_termios_input_baud_rate(struct ktermios *termios);
extern void tty_termios_encode_baud_rate(struct ktermios *termios, speed_t ibaud, speed_t obaud);
extern void tty_encode_baud_rate(struct tty_struct *tty, speed_t ibaud, speed_t obaud);
extern void tty_termios_copy_hw(struct ktermios *new, struct ktermios *old);

extern struct tty_ldisc *tty_ldisc_ref(struct tty_struct *);
extern void tty_ldisc_deref(struct tty_ldisc *);
Expand Down

0 comments on commit 4fb2f7d

Please sign in to comment.