LCOV - code coverage report
Current view: top level - drivers/tty - tty_baudrate.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 0 54 0.0 %
Date: 2023-04-06 08:38:28 Functions: 0 4 0.0 %

          Line data    Source code
       1             : // SPDX-License-Identifier: GPL-2.0
       2             : /*
       3             :  *  Copyright (C) 1991, 1992, 1993, 1994  Linus Torvalds
       4             :  */
       5             : 
       6             : #include <linux/types.h>
       7             : #include <linux/kernel.h>
       8             : #include <linux/termios.h>
       9             : #include <linux/tty.h>
      10             : #include <linux/export.h>
      11             : #include "tty.h"
      12             : 
      13             : 
      14             : /*
      15             :  * Routine which returns the baud rate of the tty
      16             :  *
      17             :  * Note that the baud_table needs to be kept in sync with the
      18             :  * include/asm/termbits.h file.
      19             :  */
      20             : static const speed_t baud_table[] = {
      21             :         0, 50, 75, 110, 134, 150, 200, 300, 600, 1200, 1800, 2400,
      22             :         4800, 9600, 19200, 38400, 57600, 115200, 230400, 460800,
      23             : #ifdef __sparc__
      24             :         76800, 153600, 307200, 614400, 921600, 500000, 576000,
      25             :         1000000, 1152000, 1500000, 2000000
      26             : #else
      27             :         500000, 576000, 921600, 1000000, 1152000, 1500000, 2000000,
      28             :         2500000, 3000000, 3500000, 4000000
      29             : #endif
      30             : };
      31             : 
      32             : static const tcflag_t baud_bits[] = {
      33             :         B0, B50, B75, B110, B134, B150, B200, B300, B600, B1200, B1800, B2400,
      34             :         B4800, B9600, B19200, B38400, B57600, B115200, B230400, B460800,
      35             : #ifdef __sparc__
      36             :         B76800, B153600, B307200, B614400, B921600, B500000, B576000,
      37             :         B1000000, B1152000, B1500000, B2000000
      38             : #else
      39             :         B500000, B576000, B921600, B1000000, B1152000, B1500000, B2000000,
      40             :         B2500000, B3000000, B3500000, B4000000
      41             : #endif
      42             : };
      43             : 
      44             : static int n_baud_table = ARRAY_SIZE(baud_table);
      45             : 
      46             : /**
      47             :  *      tty_termios_baud_rate
      48             :  *      @termios: termios structure
      49             :  *
      50             :  *      Convert termios baud rate data into a speed. This should be called
      51             :  *      with the termios lock held if this termios is a terminal termios
      52             :  *      structure. Device drivers can call this function but should use
      53             :  *      ->c_[io]speed directly as they are updated.
      54             :  *
      55             :  *      Locking: none
      56             :  */
      57             : 
      58           0 : speed_t tty_termios_baud_rate(const struct ktermios *termios)
      59             : {
      60             :         unsigned int cbaud;
      61             : 
      62           0 :         cbaud = termios->c_cflag & CBAUD;
      63             : 
      64             :         /* Magic token for arbitrary speed via c_ispeed/c_ospeed */
      65           0 :         if (cbaud == BOTHER)
      66           0 :                 return termios->c_ospeed;
      67             : 
      68           0 :         if (cbaud & CBAUDEX) {
      69           0 :                 cbaud &= ~CBAUDEX;
      70           0 :                 cbaud += 15;
      71             :         }
      72           0 :         return cbaud >= n_baud_table ? 0 : baud_table[cbaud];
      73             : }
      74             : EXPORT_SYMBOL(tty_termios_baud_rate);
      75             : 
      76             : /**
      77             :  *      tty_termios_input_baud_rate
      78             :  *      @termios: termios structure
      79             :  *
      80             :  *      Convert termios baud rate data into a speed. This should be called
      81             :  *      with the termios lock held if this termios is a terminal termios
      82             :  *      structure. Device drivers can call this function but should use
      83             :  *      ->c_[io]speed directly as they are updated.
      84             :  *
      85             :  *      Locking: none
      86             :  */
      87             : 
      88           0 : speed_t tty_termios_input_baud_rate(const struct ktermios *termios)
      89             : {
      90           0 :         unsigned int cbaud = (termios->c_cflag >> IBSHIFT) & CBAUD;
      91             : 
      92           0 :         if (cbaud == B0)
      93             :                 return tty_termios_baud_rate(termios);
      94             : 
      95             :         /* Magic token for arbitrary speed via c_ispeed */
      96           0 :         if (cbaud == BOTHER)
      97           0 :                 return termios->c_ispeed;
      98             : 
      99           0 :         if (cbaud & CBAUDEX) {
     100           0 :                 cbaud &= ~CBAUDEX;
     101           0 :                 cbaud += 15;
     102             :         }
     103           0 :         return cbaud >= n_baud_table ? 0 : baud_table[cbaud];
     104             : }
     105             : EXPORT_SYMBOL(tty_termios_input_baud_rate);
     106             : 
     107             : /**
     108             :  *      tty_termios_encode_baud_rate
     109             :  *      @termios: ktermios structure holding user requested state
     110             :  *      @ibaud: input speed
     111             :  *      @obaud: output speed
     112             :  *
     113             :  *      Encode the speeds set into the passed termios structure. This is
     114             :  *      used as a library helper for drivers so that they can report back
     115             :  *      the actual speed selected when it differs from the speed requested
     116             :  *
     117             :  *      For maximal back compatibility with legacy SYS5/POSIX *nix behaviour
     118             :  *      we need to carefully set the bits when the user does not get the
     119             :  *      desired speed. We allow small margins and preserve as much of possible
     120             :  *      of the input intent to keep compatibility.
     121             :  *
     122             :  *      Locking: Caller should hold termios lock. This is already held
     123             :  *      when calling this function from the driver termios handler.
     124             :  *
     125             :  *      The ifdefs deal with platforms whose owners have yet to update them
     126             :  *      and will all go away once this is done.
     127             :  */
     128             : 
     129           0 : void tty_termios_encode_baud_rate(struct ktermios *termios,
     130             :                                   speed_t ibaud, speed_t obaud)
     131             : {
     132           0 :         int i = 0;
     133           0 :         int ifound = -1, ofound = -1;
     134           0 :         int iclose = ibaud/50, oclose = obaud/50;
     135           0 :         int ibinput = 0;
     136             : 
     137           0 :         if (obaud == 0)                 /* CD dropped */
     138           0 :                 ibaud = 0;              /* Clear ibaud to be sure */
     139             : 
     140           0 :         termios->c_ispeed = ibaud;
     141           0 :         termios->c_ospeed = obaud;
     142             : 
     143           0 :         if (((termios->c_cflag >> IBSHIFT) & CBAUD) != B0)
     144           0 :                 ibinput = 1;    /* An input speed was specified */
     145             : 
     146             :         /* If the user asked for a precise weird speed give a precise weird
     147             :          * answer. If they asked for a Bfoo speed they may have problems
     148             :          * digesting non-exact replies so fuzz a bit.
     149             :          */
     150             : 
     151           0 :         if ((termios->c_cflag & CBAUD) == BOTHER) {
     152           0 :                 oclose = 0;
     153           0 :                 if (!ibinput)
     154           0 :                         iclose = 0;
     155             :         }
     156           0 :         if (((termios->c_cflag >> IBSHIFT) & CBAUD) == BOTHER)
     157           0 :                 iclose = 0;
     158             : 
     159           0 :         termios->c_cflag &= ~CBAUD;
     160           0 :         termios->c_cflag &= ~(CBAUD << IBSHIFT);
     161             : 
     162             :         /*
     163             :          *      Our goal is to find a close match to the standard baud rate
     164             :          *      returned. Walk the baud rate table and if we get a very close
     165             :          *      match then report back the speed as a POSIX Bxxxx value by
     166             :          *      preference
     167             :          */
     168             : 
     169             :         do {
     170           0 :                 if (obaud - oclose <= baud_table[i] &&
     171           0 :                     obaud + oclose >= baud_table[i]) {
     172           0 :                         termios->c_cflag |= baud_bits[i];
     173           0 :                         ofound = i;
     174             :                 }
     175           0 :                 if (ibaud - iclose <= baud_table[i] &&
     176           0 :                     ibaud + iclose >= baud_table[i]) {
     177             :                         /* For the case input == output don't set IBAUD bits
     178             :                          * if the user didn't do so.
     179             :                          */
     180           0 :                         if (ofound == i && !ibinput) {
     181             :                                 ifound  = i;
     182             :                         } else {
     183           0 :                                 ifound = i;
     184           0 :                                 termios->c_cflag |= (baud_bits[i] << IBSHIFT);
     185             :                         }
     186             :                 }
     187           0 :         } while (++i < n_baud_table);
     188             : 
     189             :         /* If we found no match then use BOTHER. */
     190           0 :         if (ofound == -1)
     191           0 :                 termios->c_cflag |= BOTHER;
     192             :         /* Set exact input bits only if the input and output differ or the
     193             :          * user already did.
     194             :          */
     195           0 :         if (ifound == -1 && (ibaud != obaud || ibinput))
     196           0 :                 termios->c_cflag |= (BOTHER << IBSHIFT);
     197           0 : }
     198             : EXPORT_SYMBOL_GPL(tty_termios_encode_baud_rate);
     199             : 
     200             : /**
     201             :  *      tty_encode_baud_rate            -       set baud rate of the tty
     202             :  *      @tty:   terminal device
     203             :  *      @ibaud: input baud rate
     204             :  *      @obaud: output baud rate
     205             :  *
     206             :  *      Update the current termios data for the tty with the new speed
     207             :  *      settings. The caller must hold the termios_rwsem for the tty in
     208             :  *      question.
     209             :  */
     210             : 
     211           0 : void tty_encode_baud_rate(struct tty_struct *tty, speed_t ibaud, speed_t obaud)
     212             : {
     213           0 :         tty_termios_encode_baud_rate(&tty->termios, ibaud, obaud);
     214           0 : }
     215             : EXPORT_SYMBOL_GPL(tty_encode_baud_rate);

Generated by: LCOV version 1.14