main.go (2373B)
1 package main 2 3 import ( 4 "fmt" 5 "io" 6 "log" 7 8 "golang.org/x/sys/unix" 9 ) 10 11 const ttyFile = "/dev/ttyU0" 12 13 func main() { 14 fd, err := device_open(ttyFile) 15 if err != nil { 16 log.Fatal(err) 17 } 18 defer unix.Close(fd) 19 if err = setparms(fd, 115200); err != nil { 20 log.Fatal(err) 21 } 22 if err = flush(fd); err != nil { 23 log.Fatal(err) 24 } 25 26 go reader(fd) 27 writer(fd) 28 } 29 30 func reader(fd int) { 31 buf := make([]byte, 64) 32 for { 33 n, err := unix.Read(fd, buf) 34 if err == io.EOF { 35 break 36 } else if err != nil { 37 log.Printf("read from tty: %v", err) 38 break 39 } 40 log.Printf("read from tty: %q", buf[:n]) 41 _, err = unix.Write(unix.Stdout, buf[:n]) 42 if err != nil { 43 log.Printf("write to stdout: %v", err) 44 break 45 } 46 } 47 } 48 49 func writer(fd int) { 50 buf := make([]byte, 64) 51 for { 52 n, err := unix.Read(unix.Stdin, buf) 53 if n == 0 || err == io.EOF { 54 break 55 } else if err != nil { 56 log.Printf("read from stdin: %v", err) 57 break 58 } 59 log.Printf("from terminal: %q", buf[:n]) 60 _, err = unix.Write(fd, buf[:n]) 61 if err != nil { 62 log.Printf("write to tty: %v", err) 63 break 64 } 65 } 66 } 67 68 func device_open(path string) (fd int, err error) { 69 fd, err = unix.Open(path, unix.O_RDWR|unix.O_NDELAY|unix.O_NOCTTY, 0) 70 if err != nil { 71 return 0, fmt.Errorf("open: %w", err) 72 } 73 defer func() { 74 if err != nil { 75 unix.Close(fd) 76 } 77 }() 78 n, err := unix.FcntlInt(uintptr(fd), unix.F_GETFL, 0) 79 if err != nil { 80 return 0, fmt.Errorf("getfl: %w", err) 81 } 82 _, err = unix.FcntlInt(uintptr(fd), unix.F_SETFL, n&^unix.O_NDELAY) 83 if err != nil { 84 return 0, fmt.Errorf("setfl: %w", err) 85 } 86 return fd, nil 87 } 88 89 func setparms(fd int, baud int32) error { 90 tty, err := unix.IoctlGetTermios(fd, unix.TIOCGETA) 91 if err != nil { 92 return fmt.Errorf("gettermios: %w", err) 93 } 94 tty.Iflag = unix.IGNBRK 95 tty.Iflag &= ^(uint32(unix.IXON) | uint32(unix.IXOFF) | uint32(unix.IXANY)) 96 tty.Oflag = 0 97 tty.Cflag = (tty.Cflag &^ unix.CSIZE) | unix.CS8 98 tty.Cflag |= unix.CLOCAL | unix.CREAD 99 tty.Cflag &= ^uint32(unix.CSTOPB) 100 tty.Lflag = 0 101 tty.Cc[unix.VMIN] = 1 102 tty.Cc[unix.VTIME] = 5 103 tty.Ispeed = baud 104 tty.Ospeed = baud 105 err = unix.IoctlSetTermios(fd, unix.TIOCSETA, tty) 106 if err != nil { 107 return fmt.Errorf("settermios: %w", err) 108 } 109 return nil 110 } 111 112 func flush(fd int) error { 113 _, err := unix.IoctlGetInt(fd, unix.TIOCFLUSH) 114 if err != nil { 115 return fmt.Errorf("tiocflush: %w", err) 116 } 117 return nil 118 }