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 }