github.com/hugelgupf/u-root@v0.0.0-20191023214958-4807c632154c/pkg/termios/termios_linux.go (about)

     1  // Copyright 2015-2017 the u-root Authors. All rights reserved
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package termios
     6  
     7  import (
     8  	"fmt"
     9  	"os"
    10  	"os/exec"
    11  	"path/filepath"
    12  	"syscall"
    13  
    14  	"golang.org/x/sys/unix"
    15  )
    16  
    17  // TTY is a wrapper that only allows Read and Write.
    18  type TTY struct {
    19  	f *os.File
    20  }
    21  
    22  func New() (*TTY, error) {
    23  	f, err := os.OpenFile("/dev/tty", os.O_RDWR, 0)
    24  	if err != nil {
    25  		return nil, err
    26  	}
    27  	return &TTY{f: f}, nil
    28  }
    29  
    30  func NewTTYS(port string) (*TTY, error) {
    31  	f, err := os.OpenFile(filepath.Join("/dev", port), unix.O_RDWR|unix.O_NOCTTY|unix.O_NONBLOCK, 0620)
    32  	if err != nil {
    33  		return nil, err
    34  	}
    35  	return &TTY{f: f}, nil
    36  }
    37  
    38  func (t *TTY) Read(b []byte) (int, error) {
    39  	return t.f.Read(b)
    40  }
    41  
    42  func (t *TTY) Write(b []byte) (int, error) {
    43  	return t.f.Write(b)
    44  }
    45  
    46  func GetTermios(fd uintptr) (*unix.Termios, error) {
    47  	return unix.IoctlGetTermios(int(fd), unix.TCGETS)
    48  }
    49  
    50  func (t *TTY) Get() (*unix.Termios, error) {
    51  	return GetTermios(t.f.Fd())
    52  }
    53  
    54  func SetTermios(fd uintptr, ti *unix.Termios) error {
    55  	return unix.IoctlSetTermios(int(fd), unix.TCSETS, ti)
    56  }
    57  
    58  func (t *TTY) Set(ti *unix.Termios) error {
    59  	return SetTermios(t.f.Fd(), ti)
    60  }
    61  
    62  func GetWinSize(fd uintptr) (*unix.Winsize, error) {
    63  	return unix.IoctlGetWinsize(int(fd), unix.TIOCGWINSZ)
    64  }
    65  
    66  func (t *TTY) GetWinSize() (*unix.Winsize, error) {
    67  	return GetWinSize(t.f.Fd())
    68  }
    69  
    70  func SetWinSize(fd uintptr, w *unix.Winsize) error {
    71  	return unix.IoctlSetWinsize(int(fd), unix.TIOCSWINSZ, w)
    72  }
    73  
    74  func (t *TTY) SetWinSize(w *unix.Winsize) error {
    75  	return SetWinSize(t.f.Fd(), w)
    76  }
    77  
    78  func (t *TTY) Ctty(c *exec.Cmd) {
    79  	c.Stdin, c.Stdout, c.Stderr = t.f, t.f, t.f
    80  	if c.SysProcAttr == nil {
    81  		c.SysProcAttr = &syscall.SysProcAttr{}
    82  	}
    83  	c.SysProcAttr.Setctty = true
    84  	c.SysProcAttr.Setsid = true
    85  	c.SysProcAttr.Ctty = int(t.f.Fd())
    86  }
    87  
    88  func MakeRaw(term *unix.Termios) *unix.Termios {
    89  	raw := *term
    90  	raw.Iflag &^= unix.IGNBRK | unix.BRKINT | unix.PARMRK | unix.ISTRIP | unix.INLCR | unix.IGNCR | unix.ICRNL | unix.IXON
    91  	raw.Oflag &^= unix.OPOST
    92  	raw.Lflag &^= unix.ECHO | unix.ECHONL | unix.ICANON | unix.ISIG | unix.IEXTEN
    93  	raw.Cflag &^= unix.CSIZE | unix.PARENB
    94  	raw.Cflag |= unix.CS8
    95  
    96  	raw.Cc[unix.VMIN] = 1
    97  	raw.Cc[unix.VTIME] = 0
    98  
    99  	return &raw
   100  }
   101  
   102  // MakeSerialBaud updates the Termios to set the baudrate
   103  func MakeSerialBaud(term *unix.Termios, baud int) (*unix.Termios, error) {
   104  	t := *term
   105  	rate, ok := baud2unixB[baud]
   106  	if !ok {
   107  		return nil, fmt.Errorf("%d: Unrecognized baud rate", baud)
   108  	}
   109  
   110  	t.Cflag &^= unix.CBAUD
   111  	t.Cflag |= rate
   112  	t.Ispeed = rate
   113  	t.Ospeed = rate
   114  
   115  	return &t, nil
   116  }
   117  
   118  // MakeSerialDefault updates the Termios to typical serial configuration:
   119  // - Ignore all flow control (modem, hardware, software...)
   120  // - Translate carriage return to newline on input
   121  // - Enable canonical mode: Input is available line by line, with line editing
   122  //   enabled (ERASE, KILL are supported)
   123  // - Local ECHO is added (and handled by line editing)
   124  // - Map newline to carriage return newline on output
   125  func MakeSerialDefault(term *unix.Termios) *unix.Termios {
   126  	t := *term
   127  	/* Clear all except baud, stop bit and parity settings */
   128  	t.Cflag &= unix.CBAUD | unix.CSTOPB | unix.PARENB | unix.PARODD
   129  	/* Set: 8 bits; ignore Carrier Detect; enable receive */
   130  	t.Cflag |= unix.CS8 | unix.CLOCAL | unix.CREAD
   131  	t.Iflag = unix.ICRNL
   132  	t.Lflag = unix.ICANON | unix.ISIG | unix.ECHO | unix.ECHOE | unix.ECHOK | unix.ECHOKE | unix.ECHOCTL
   133  	/* non-raw output; add CR to each NL */
   134  	t.Oflag = unix.OPOST | unix.ONLCR
   135  	/* reads will block only if < 1 char is available */
   136  	t.Cc[unix.VMIN] = 1
   137  	/* no timeout (reads block forever) */
   138  	t.Cc[unix.VTIME] = 0
   139  	t.Line = 0
   140  
   141  	return &t
   142  }